Latin-1 i fabryka Unicode w Pythonie
Mam skrypt Pythona 2.6, który dławi się na znaki specjalne, zakodowane w Latin-1, które pobieram z bazy danych SQL Server. Chciałbym wydrukować te znaki, ale jestem nieco ograniczony, ponieważ używam biblioteki, która wywołujeunicode
i nie wiem, jak sprawić, by Python używał kodeka innego niżascii
.
Skrypt jest prostym narzędziem do zwracania danych wyszukiwania z bazy danych bez konieczności wykonywania SQL bezpośrednio w edytorze SQL. używamPrettyTable 0,5 biblioteki do wyświetlania wyników.
Rdzeniem skryptu jest ten fragment kodu. Krotki, które otrzymuję od kursora, zawierają dane całkowite i łańcuchowe oraz dane Unicode. (Użyłbymadodbapi
zamiastpyodbc
, co dałoby mi Unicode, aleadodbapi
daje mi inne problemy.)
x = pyodbc.connect(cxnstring)
r = x.cursor()
r.execute(sql)
t = PrettyTable(columns)
for rec in r:
t.add_row(rec)
r.close()
x.close()
t.set_field_align("ID", 'r')
t.set_field_align("Name", 'l')
print t
AleName
kolumna może zawierać znaki spoza zakresu ASCII. Czasem otrzymam komunikat o błędzie podobny do tego w linii 222prettytable.pyc
, kiedy dotrze dot.add_row
połączenie:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xed in position 12: ordinal not in range(128)
To jest linia 222 wprettytable.py
. To używaunicode
, co jest źródłem moich problemów, nie tylko w tym skrypcie, ale w innych skryptach Pythona, które napisałem.
for i in range(0,len(row)):
if len(unicode(row[i])) > self.widths[i]: # This is line 222
self.widths[i] = len(unicode(row[i]))
Proszę mi powiedzieć, co tu źle robię. Jak mogę to zrobićunicode
pracować bez hakowaniaprettytable.py
lub jakiejkolwiek innej biblioteki, z której korzystam? Czy jest na to jakiś sposób?
EDYCJA: Błąd nie występuje wprint
oświadczenie, ale nat.add_row
połączenie.
EDIT: Z pomocą Bastiena Léonarda wymyśliłem następujące rozwiązanie. To nie jest panaceum, ale działa.
x = pyodbc.connect(cxnstring)
r = x.cursor()
r.execute(sql)
t = PrettyTable(columns)
for rec in r:
urec = [s.decode('latin-1') if isinstance(s, str) else s for s in rec]
t.add_row(urec)
r.close()
x.close()
t.set_field_align("ID", 'r')
t.set_field_align("Name", 'l')
print t.get_string().encode('latin-1')
Skończyło się na tym, że musiałem dekodować po drodze i kodować w drodze wyjścia. Wszystko to sprawia, że mam nadzieję, że wszyscy porowią swoje biblioteki do Pythona 3.x wcześniej niż później!