2016-04-18 6 views
5

मैं pypyodbc के माध्यम से पायथन में प्रश्न भेजकर एक एमएसएसएलएल डेटाबेस से पढ़ सकता हूं।pyodbc और mSSQL का उपयोग करते हुए एक nvarchar फ़ील्ड के साथ इस यूनिकोडडेकोड एरर का कारण क्या है?

अधिकतर यूनिकोड वर्ण सही ढंग से संभाले जाते हैं, लेकिन मैंने एक निश्चित चरित्र को मारा है जो त्रुटि का कारण बनता है।

सवाल में क्षेत्र

----- 
|100| 
|111| 
----- 

प्रकार nvarchar(50) की है और इस चरित्र "" जो मेरे लिए renders इस तरह एक सा के साथ शुरू होता ... उस नंबर हेक्स 0x100111 है तो यह चरित्र supplementary private use area-b u+100111 है। हालांकि दिलचस्प बात यह है कि यदि यह बाइनरी 0b100111 है तो यह एक एस्ट्रोफ़े है, क्या यह हो सकता है कि डेटा अपलोड होने पर गलत एन्कोडिंग का उपयोग किया गया हो? यह क्षेत्र चीनी डाक पते का हिस्सा संग्रहित कर रहा है।

त्रुटि संदेश

UnicodeDecodeError: 'utf16' codec can't decode bytes in position 0-1: unexpected end of data

यहाँ यह पूर्ण में है ...

Traceback (most recent call last): File "question.py", line 19, in <module> 
    results.fetchone() File "/VIRTUAL_ENVIRONMENT_DIR/local/lib/python2.7/site-packages/pypyodbc.py", line 1869, in fetchone 
    value_list.append(buf_cvt_func(from_buffer_u(alloc_buffer))) File "/VIRTUAL_ENVIRONMENT_DIR/local/lib/python2.7/site-packages/pypyodbc.py", line 482, in UCS_dec 
    uchar = buffer.raw[i:i + ucs_length].decode(odbc_decoding) File "/VIRTUAL_ENVIRONMENT_DIR/lib/python2.7/encodings/utf_16.py", line 16, in decode 
    return codecs.utf_16_decode(input, errors, True) UnicodeDecodeError: 'utf16' codec can't decode bytes in position 0-1: unexpected end of data 

यहाँ कुछ न्यूनतम reproducing कोड है शामिल हैं ...

import pypyodbc 

connection_string = (
    "DSN=sqlserverdatasource;" 
    "UID=REDACTED;" 
    "PWD=REDACTED;" 
    "DATABASE=obi_load") 

connection = pypyodbc.connect(connection_string) 

cursor = connection.cursor() 

query_sql = (
    "SELECT address_line_1 " 
    "FROM address " 
    "WHERE address_id == 'REDACTED' ") 

with cursor.execute(query_sql) as results: 
    row = results.fetchone() # This is the line that raises the error. 
    print row 

यहाँ का एक हिस्सा है मेरा /etc/freetds/freetds.conf

[global] 
; tds version = 4.2 
; dump file = /tmp/freetds.log 
; debug flags = 0xffff 
; timeout = 10 
; connect timeout = 10 
    text size = 64512 

[sqlserver] 
host = REDACTED 
port = 1433 
tds version = 7.0 
client charset = UTF-8 

मैंने client charset = UTF-16 के साथ भी कोशिश की है और उस रेखा को सभी को एक साथ छोड़ दिया है।

यहाँ मेरी /etc/odbc.ini

[sqlserverdatasource] 
Driver = FreeTDS 
Description = ODBC connection via FreeTDS 
Trace = No 
Servername = sqlserver 
Database = REDACTED 

से प्रासंगिक हिस्सा है यहाँ से प्रासंगिक हिस्सा है मेरी /etc/odbcinst.ini

[FreeTDS] 
Description = TDS Driver (Sybase/MS SQL) 
Driver = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so 
Setup = /usr/lib/x86_64-linux-gnu/odbc/libtdsS.so 
CPTimeout = 
CPReuse = 
UsageCount = 1 

मैं इस समस्या के परिणाम, ब्लॉक को छोड़कर/एक कोशिश में प्राप्त करने में कठिनाई दूर फेंक कर काम कर सकते हैं कोई भी पंक्तियां जो UnicodeDecodeError उठाती हैं, लेकिन क्या कोई समाधान है? क्या मैं सिर्फ अनावश्यक चरित्र को फेंक सकता हूं, या कोई त्रुटि उत्पन्न किए बिना इस लाइन को लाने का कोई तरीका है?

यह असंभव नहीं है कि कुछ खराब डेटा डेटाबेस पर समाप्त हो गया है।

मैंने इस साइट के संबंधित प्रश्नों की जांच की है और इसकी कोई किस्मत नहीं है।

+1

आप http://stackoverflow.com/questions/18357675/unicodedecodeerror-unexpected-end-of-data को देखा है? – snakecharmerb

+1

यदि आप 'master.cys.fn_varbintohexstr चुनें) (CONVERT (VARBINARY, [address_line_1])) [पता] से foo ... '? यह आपको टेक्स्ट मूल्य की शुरुआत में बिल्कुल सही दिखाना चाहिए। –

+0

@ गॉर्ड थॉम्पसन 0x4700520045004e00410044004a00c400520047004100540041004e002000 –

उत्तर

0

इस समस्या को अंततः काम किया गया था, मुझे संदेह है कि समस्या यह थी कि पाठ में एक एन्कोडिंग का एक चरित्र था जिसमें टेबल की स्थापना के दौरान कुछ हैकी विधि के माध्यम से एक और घोषित एन्कोडिंग के साथ एक क्षेत्र में हथौड़ा लगाया गया था। एक कर्सर को बनाने से पहले

conn.setencoding('utf-8') 

तुरंत:

0

मैं इस मुद्दे को इस का उपयोग करके अपने आप को तय की।

जहां conn कनेक्शन ऑब्जेक्ट है।

मैं fetchall() के साथ लाखों पंक्तियों को ला रहा था, और एक लेनदेन के बीच में जो मैन्युअल रूप से पूर्ववत करने के लिए बेहद महंगा होगा, इसलिए मैं केवल अमान्य लोगों को छोड़ने का जोखिम नहीं उठा सकता था।

स्रोत जहाँ मैं समाधान नहीं मिला: https://github.com/mkleehammer/pyodbc/issues/112#issuecomment-264734456

+0

दिलचस्प है, लेकिन एमएसएसएलएल यूटीएफ -16LE का उपयोग करता है, जो कि पीओओडीबीसी डिफ़ॉल्ट रूप से भी उपयोग करता है, इसलिए मैं सामान्य परिस्थितियों में मदद के लिए यूटीएफ -8 निर्दिष्ट करने की अपेक्षा नहीं करता। फिर भी, अगर ऐसा लगता है कि यह आपकी मदद करता है तो यह उन लोगों की मदद कर सकता है जो वास्तव में यूटीएफ -8 को एक एमएसएसएलएल डेटाबेस में भर चुके हैं। –

+0

मैं Azure SQL का उपयोग कर रहा हूं, जिसमें कुछ क्विर्क हो सकते हैं जो इसे अलग करते हैं? किसी भी तरह से, मुझे यह विचित्र लगता है, क्योंकि उस डेटाबेस में डेटा एकमात्र तरीका उसी कोडबेस/'pyodbc' ड्राइवर के माध्यम से होता है जिसे मैं डेटा लाने के लिए उपयोग कर रहा था। –

संबंधित मुद्दे