हाल के संस्करणों में पायथन के स्ट्रिंग फॉर्मेटर परिवर्तनों ने MySQL कनेक्टर को तोड़ दिया है?

Nov 28 2020

मैं एक सरल लिख रहा हूं - या यह सरल होना चाहिए - ट्विटर की एपीआई से ट्वीट प्राप्त करने के लिए स्क्रिप्ट (मेरे पास डेवलपर / ऐप कुंजियाँ हैं और मैं Tweepy इंटरफ़ेस का उपयोग कर रहा हूं, स्क्रैपिंग या उस तरह का कुछ भी नहीं - मैं कुछ के लिए Tweepy को खोद सकता हूं आधुनिक एपीआई लेकिन यह लगभग निश्चित रूप से नहीं है कि इस मुद्दे का क्या कारण है)।

मेरे पास एक MySQL उदाहरण है जिसे मैं कनेक्ट करता हूं और ठीक-ठीक क्वेरी कर सकता हूं, जब तक कि यह ट्वीट डालने का समय नहीं आता है - जिसमें बहुत सारे विशेष वर्ण हैं, लगभग अनिवार्य रूप से। स्पष्ट होने के लिए, मैं MySQL के लिए आधिकारिक पायथन ड्राइवर / कनेक्टर का उपयोग कर रहा हूं।

import mysql.connector
from mysql.connector import errorcode

अब, मुझे पता है कि StackOverflow, थ्रेड्स से लैस है जहां लोगों को मेरी सटीक त्रुटि मिलती है - बस MySQL सिंटैक्स मैनुअल को जांचने के लिए। ये धागे, जो कि सभी पुराने नहीं हैं (और मैं नवीनतम पायथन का उपयोग नहीं कर रहा हूं, मैं कुछ एनएलपी पुस्तकालयों के साथ संगतता के लिए 3.7.9 का उपयोग करता हूं) उत्तर पर जोर देते हैं कि स्ट्रिंग को एक पुराने अक्षर में रखना है- कर्सर के साथ शैली प्रारूप स्ट्रिंग .execute विधि, स्ट्रिंग चर प्लेसहोल्डर्स को उद्धरणों में संलग्न करने के लिए, और एक खाली दूसरे मान के साथ एक टपल पास करने के लिए, यदि मेरे मामले में, केवल एक चर डाला जाना है। यह MySQL वेबसाइट पर एक बग रिपोर्ट प्रतिक्रिया के भाग के रूप में पोस्ट किया गया एक समाधान भी है - और अभी तक, मुझे कोई सफलता नहीं मिली है।

यहाँ पर मुझे क्या मिला है - यहाँ और आधिकारिक डेटाबेस वेबसाइट के दर्जनों पृष्ठों पर दिए गए निर्देशों का पालन करें:

for tweet in tweepy.Cursor(twilek.search, q=keyword, tweet_mode='extended').items():
            twi_tweet = tweet.full_text
            print(twi_tweet)
            twi_tweet = twi_tweet.encode('utf8')
            requests_total+=1
            os.environ['TWITTER_REQUESTS'] = str(requests_total)
            requests_total = int(os.environ.get('TWITTER_REQUESTS'))
            # insert the archived tweet text into the database table
            sql = 'USE hate_tweets'
            ms_cur.execute(sql)
            twi_tweet = str(twi_tweet)
            insert_tweet = re.sub(r'[^A-Za-z0-9 ]+', '', twi_tweet)
            ms_cur.execute("INSERT INTO tweets_lgbt (text) VALUES %s" % (insert_tweet,))
            cnx.commit()
            print(ms_cur.rowcount, "record inserted.")

(ट्विलेक मेरा कर्सर ऑब्जेक्ट है क्योंकि मैं एक डॉर्क हूं)

अपेक्षित परिणाम : स्ट्रिंग फ़ॉर्मेटर ने MySQL को एक संशोधित ट्वीट स्ट्रिंग से गुज़ारा है जो इसे संसाधित कर सकता है और tweets_lgbt तालिका में एक पंक्ति के रूप में जोड़ सकता है

वास्तविक परिणाम : किसी भी ट्वीट के लिए सिंटैक्स त्रुटि पर प्रविष्टि विफल हो जाती है

मैं इतनी दूर जा रहा हूँ के रूप में regex का उपयोग करने के लिए सब कुछ पट्टी लेकिन अल्फ़ान्यूमेरिक और रिक्त स्थान का उपयोग करें - एक ही मुद्दा। मैं सोच रहा था कि क्या वर्तमान पायथन संस्करणों के नए स्ट्रिंग प्रारूप की विशेषताओं ने इस कनेक्टर के साथ संगतता को तोड़ दिया है? मैं आधिकारिक ड्राइवर का उपयोग करना पसंद करता हूं, लेकिन अगर मुझे चाहिए तो मैं एक ओआरएम पर स्विच करूंगा। (मैंने एफ स्ट्रिंग्स जैसी नई सुविधाओं की कोशिश की, और पाया कि वे एक ही परिणाम का कारण बने।)

जवाब

2 CodeIt Nov 28 2020 at 13:53

यह आपको अपनी तालिका में एक पंक्ति सम्मिलित करनी चाहिए,

insert_tweet = "ABCEFg 9 XYZ"
"INSERT INTO tweets_lgbt (text) VALUES ('%s');"%(insert_tweet)
"INSERT INTO tweets_lgbt (text) VALUES ('ABCEFg 9 XYZ');"

ध्यान देने योग्य बातें

  1. स्ट्रिंग सूत्रकार के तर्क किसी कार्य के तर्कों की तरह हैं। इसलिए, आप एक स्ट्रिंग को वहाँ टुपल में बदलने के लिए अंत में एक अल्पविराम नहीं जोड़ सकते हैं।

  2. आप एक बार में एक से अधिक मान सम्मिलित करने के लिए कोशिश कर रहे हैं, तो आप उपयोग कर सकते हैं cursor.executemany या इस जवाब ।

2 snakecharmerb Nov 28 2020 at 14:30

मेरे पास ये अवलोकन हैं:

  • VALUESखंड की आवश्यकता है कोष्ठकोंVALUES (%s)
  • मानों के उद्धरण / भागने को कर्सर की executeविधि में प्रत्यायोजित किया जाना चाहिए , एसक्यूएल में निर्विवाद प्लेसहोल्डर्स का उपयोग करके और मानों को दूसरे तर्क के रूप में पारित किया जाता है: cursor.execute(sql, (tweet_text,))याcursor.executemany(sql, [(tweet_text1,), (tweet_text2,)])
  • एक बार इन चरणों को लागू करने के बाद एन्कोडिंग / स्ट्रिंग / रेगेक्स-इफिसिंग की कोई आवश्यकता नहीं होती है: मान twi_textलेना एक है strऔर डेटाबेस का चारसेट / टकराव पूर्ण यूटीएफ -8 रेंज (उदाहरण के लिए utf8mb4) का समर्थन करता है, तो सम्मिलित करना सफल होना चाहिए।
    • विशेष रूप से, एन्कोडिंग strऔर फिर strपरिणाम पर कॉल करने से बचना है: आप के साथ समाप्त होता है"b'my original string'"

प्रश्न में कोड का यह संशोधित संस्करण मेरे लिए काम करता है:

import mysql.connector

DDL1 = """DROP TABLE IF EXISTS tweets_lgbt"""
DDL2 = """\
CREATE TABLE tweets_lgbt (
    `text` VARCHAR (256))
"""

# From https://twitter.com/AlisonMitchell/status/1332567013701500928?s=20
insert_tweet = """\
Particularly pleased to see @SarahStylesAU
 quoted in this piece for the work she did
👌

Thrive like a girl: Why women's cricket in Australia is setting the standard
"""

# Older connector releases don't support with... 
with mysql.connector.connect(database='test') as cnx:
    with cnx.cursor() as ms_cur:

        ms_cur.execute(DDL1)
        ms_cur.execute(DDL2)

        ms_cur.execute("INSERT INTO tweets_lgbt (`text`) VALUES (%s)",  (insert_tweet,))
        cnx.commit()
        print(ms_cur.rowcount, "record inserted.")