У меня есть сценарий Python 2.6, который заглатывает специальные символы, закодированные в Latin-1, которые я извлекаю из базы данных SQL Server. Я хотел бы напечатать эти символы, но я несколько ограничен, потому что я использую библиотеку, которая вызывает фабрику unicode
, и я не знаю, как заставить Python использовать кодек, отличный от ascii
.
Сценарий - это простой инструмент для возврата данных поиска из базы данных без необходимости выполнения SQL непосредственно в редакторе SQL. Я использую библиотеку PrettyTable 0.5 для отображения результатов.
Суть скрипта - это бит кода. Кортежи, которые я получаю от курсора, содержат целочисленные и строковые данные, а не данные Unicode. (Я бы использовал adodbapi
вместо pyodbc
, что дало бы мне Unicode, но adodbapi
доставляет мне другие проблемы.)
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
Но столбец Name
может содержать символы, выходящие за пределы диапазона ASCII. Иногда я получаю сообщение об ошибке, подобное этому, в строке 222 из prettytable.pyc
, когда оно достигает вызова t.add_row
:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xed in position 12: ordinal not in range(128)
Это строка 222 в prettytable.py
. Он использует unicode
, который является источником моих проблем, и не только в этом скрипте, но и в других скриптах Python, которые я написал.
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]))
Пожалуйста, скажите мне, что я здесь делаю неправильно. Как я могу заставить unicode
работать без взлома prettytable.py
или любой другой библиотеки, которую я использую? Есть ли способ сделать это?
EDIT: ошибка возникает не в операторе print
, а в вызове t.add_row
.
РЕДАКТИРОВАТЬ: С помощью Бастиена Леонара, я пришел к следующему решению. Это не панацея, но она работает.
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')
Мне пришлось декодировать при входе и кодировать при выходе. Все это заставляет меня надеяться, что все перенесут свои библиотеки в Python 3.x раньше, чем позже!