Posso leggere da un database MSSQL inviando query in python tramite pypyodbc.Qual è la causa di questo errore UnicodeDecodeError con un campo nvarchar che utilizza pyodbc e MSSQL?
La maggior parte dei caratteri unicode viene gestita correttamente, ma ho colpito un determinato carattere che causa un errore.
Il campo in questione è di tipo nvarchar(50)
e inizia con questo carattere "" che rende per me un po 'come questo ...
-----
|100|
|111|
-----
Se questo numero è esadecimale 0x100111
allora è il carattere supplementary private use area-b u+100111
. Anche se interessante, se è binario 0b100111
allora è un apostrofo, potrebbe essere che la codifica sbagliata è stata utilizzata quando i dati sono stati caricati? Questo campo sta memorizzando parte di un indirizzo postale cinese.
Il messaggio di errore include
UnicodeDecodeError: 'utf16' codec can't decode bytes in position 0-1: unexpected end of data
Qui è in piena ...
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
Ecco po 'di codice riproduzione minimal ...
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
Ecco un pezzo di my /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
Ho anche provato con client charset = UTF-16
e omettendo quella linea tutti insieme.
Ecco il pezzo in questione dal mio /etc/odbc.ini
[sqlserverdatasource]
Driver = FreeTDS
Description = ODBC connection via FreeTDS
Trace = No
Servername = sqlserver
Database = REDACTED
Ecco il pezzo rilevante dal mio /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
posso risolvere questo problema prendendo i risultati in un blocco try/except, buttare via qualsiasi riga che genera un UnicodeDecodeError
, ma c'è una soluzione? Posso buttare via solo il personaggio indecodibile, o c'è un modo per recuperare questa riga senza generare un errore?
Non è inconcepibile che alcuni dati non validi siano finiti nel database.
Ho cercato su Google e controllato le domande relative a questo sito, ma non ho avuto fortuna.
Hai visto http://stackoverflow.com/questions/18357675/unicodedecodeerror-unexpected-end-of-data? – snakecharmerb
Cosa ottieni se si seleziona SELECT master.sys.fn_varbintohexstr (CONVERT (VARBINARY, [address_line_1])) AS foo FROM [address] ... '? Questo dovrebbe mostrarti esattamente ciò che è all'inizio del valore del testo. –
@GordThompson 0x4700520045004e00410044004a00c400520047004100540041004e002000 –