sqlite3.ProgrammingError: जब तक आप एक text_factory का उपयोग नहीं करते हैं, तब तक 8-बिट बायस्ट्रेस का उपयोग नहीं करना चाहिए


90

पायथन में SQLite3 का उपयोग करते हुए, मैं UTF-8 HTML कोड के स्निपेट के एक संपीड़ित संस्करण को संग्रहीत करने का प्रयास कर रहा हूं।

कोड इस तरह दिखता है:

...
c = connection.cursor()
c.execute('create table blah (cid integer primary key,html blob)')
...
c.execute('insert or ignore into blah values (?, ?)',(cid, zlib.compress(html)))

किस बिंदु पर त्रुटि मिलती है:

sqlite3.ProgrammingError: You must not use 8-bit bytestrings unless you use a text_factory that can interpret 8-bit bytestrings (like text_factory = str). It is highly recommended that you instead just switch your application to Unicode strings.

अगर मैं 'ब्लॉब' के बजाय 'टेक्स्ट' का उपयोग करता हूं और HTML स्निपेट को संपीड़ित नहीं करता हूं, तो यह सभी ठीक काम करता है (हालांकि db बड़े पैमाने पर है)। जब मैं पायथन ज़्लिब लाइब्रेरी के माध्यम से 'ब्लॉब' और कम्प्रेस का उपयोग करता हूं, तो मुझे उपरोक्त त्रुटि संदेश मिलता है। मैंने चारों ओर देखा, लेकिन इस के लिए एक सरल उत्तर नहीं मिला।

जवाबों:


94

यदि आप sqlite3 में यूनिकोड स्ट्रिंग के बजाय 8-बिट स्ट्रिंग्स का उपयोग करना चाहते हैं, तो sqlite कनेक्शन के लिए लगभग टेक्स्ट_फैक्ट्री सेट करें:

connection = sqlite3.connect(...)
connection.text_factory = str

7
यह आपको अलग-अलग एनकोडिंग के साथ समस्याएं दे सकता है, क्योंकि आप अभी भी द्विआधारी डेटा को पाठ के रूप में पार्स करने की कोशिश कर रहे हैं। इसके बजाय sqlite3.Binary का उपयोग करना सबसे अच्छा है।
मारियोविलास

35

समाधान मिल गया, मुझे खोज करने में बस थोड़ा और समय बिताना चाहिए था।

समाधान एक पायथन 'बफर' के रूप में 'कास्ट' करने के लिए है, जैसे:

c.execute('insert or ignore into blah values (?, ?)',(cid, buffer(zlib.compress(html))))

उम्मीद है कि यह किसी और की मदद करेगा।


1
जब मैंने ऐसा किया, तो मेरा डेटाबेस बेस 36 पाठ से भरा था, जो डेटाबेस को सीधे ब्लॉब को स्टोर करने से बड़ा बनाता है।
ब्रायन मिंटन

3
यह गलत है, आपको sqlite3 का उपयोग करना चाहिए। इसके बजाय दस्तावेज़ीकरण कहता है।
मारियोविलास

यह sqlite3.Binary की तरह दिखता है () बस बफर का एक उपनाम है (), कम से कम github.com/ghaering/pysqlite/blob/master/lib/dbapi2.py#5454
Stepvegt

हुह। और यह भी दिखता है कि pysqlite डॉक्स का यह खंड वास्तव में बफर () उपयोग को प्रोत्साहित करता है: "निम्न पायथन प्रकारों को इस प्रकार बिना किसी समस्या के SQLite में भेजा जा सकता है: ..." [अजगर प्रकार] बफर ... [SQLite प्रकार] BLOB " docs.python.org/2/library/sqlite3.html#introduction
stevegt

35

BLOB प्रकार के साथ काम करने के लिए, आपको पहले अपने zlib संपीड़ित स्ट्रिंग को बाइनरी डेटा में बदलना होगा - अन्यथा sqlite इसे टेक्स्ट स्ट्रिंग के रूप में संसाधित करने का प्रयास करेगा। यह sqlite3.Binary () के साथ किया जाता है। उदाहरण के लिए:

c.execute('insert or ignore into blah values (?, ?)',(cid, 
sqlite3.Binary(zlib.compress(html))))

यह काम। हालांकि, मैं सोच रहा था कि इसकी आवश्यकता क्यों है। क्या "कॉलम" प्रकार पहले से ही इंगित करता है कि इस कॉलम में डेटा द्विआधारी है? पायथन 2 में नोट स्ट्रिंग या तो टेक्स्ट या बाइनरी हो सकता है। नहीं चाहिए sqlite3 सिर्फ वस्तु (zlib संपीड़ित स्ट्रिंग) को BLOB प्रकार के लिए द्विआधारी के रूप में मानते हैं?
user1783732

मुझे नहीं लगता कि सही डेटा प्रकारों के परामर्श के लिए पाइथन की स्मृति में पूरा डेटाबेस स्कीमा है - सबसे अधिक संभावना है कि यह रनटाइम के प्रकारों का अनुमान लगाता है कि आप इसे किस आधार पर पास करते हैं, इसलिए एक बाइनरी स्ट्रिंग को टेक्स्ट स्ट्रिंग से अलग नहीं किया जा सकता है।
मारियोविलास

क्योंकि SQLite डायनामिक प्रकार का उपयोग करता है: sqlite.org/datatype3.html @ user1783732
लेस्टर चेउंग

1

वाक्य - विन्यास:

5 प्रकार के संभावित भंडारण: NULL, INTEGER, TEXT, REAL और BLOB

BLOB आमतौर पर अचार वाले मॉडल या डिल अचार वाले मॉडल को स्टोर करने के लिए उपयोग किया जाता है

> cur.execute('''INSERT INTO Tablename(Col1, Col2, Col3, Col4) VALUES(?,?,?,?)''', 
                                      [TextValue, Real_Value, Buffer(model), sqlite3.Binary(model2)])
> conn.commit()

> # Read Data:
> df = pd.read_sql('SELECT * FROM Model, con=conn) 
> model1 = str(df['Col3'].values[0]))
> model2 = str(df['Col'].values[0]))

0

आप कच्चे आउटपुट के बजाय repr (html) का उपयोग करके मूल्य संग्रहीत कर सकते हैं और फिर उपयोग के लिए मान प्राप्त करते समय eval (html) का उपयोग कर सकते हैं।

c.execute('insert or ignore into blah values (?, ?)',(1, repr(zlib.compress(html))))

1
इस तरह से eval और repr का उपयोग करना बहुत गंदा है। कोई फर्क नहीं पड़ता कि आप डेटा-स्रोत पर कितना भरोसा करते हैं।
जेसन फ्राइड

मैं मानता हूं, यहां कुछ भी eval () से बेहतर है। सही समाधान sqlite3.Binary का उपयोग कर रहा है, लेकिन यदि आप किसी कारण से नहीं कर सकते हैं, तो डेटा को सुरक्षित तरीके से एनकोड करना बेहतर है - उदाहरण के लिए बेस 64 के साथ।
मारियोविलास
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.