Latin-1 e a fábrica unicode em Python
Eu tenho um script Python 2.6 que está engasgando com caracteres especiais, codificados em Latin-1, que estou recuperando de um banco de dados do SQL Server. Gostaria de imprimir esses caracteres, mas estou um pouco limitado porque estou usando uma biblioteca que chama ounicode
factory, e eu não sei como fazer Python usar um codec diferente doascii
.
O script é uma ferramenta simples para retornar dados de pesquisa de um banco de dados sem ter que executar o SQL diretamente em um editor de SQL. Eu uso oPrettyTable 0,5 biblioteca para exibir os resultados.
O núcleo do script é esse pequeno código. As tuplas que recebo do cursor contêm dados inteiros e de string, e nenhum dado Unicode. (Eu usariaadodbapi
ao invés depyodbc
, o que me levaria a Unicode, masadodbapi
me dá outros problemas.)
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
Mas oName
coluna pode conter caracteres que estão fora do intervalo ASCII. Às vezes, recebo uma mensagem de erro como esta, na linha 222 deprettytable.pyc
, quando chega aot.add_row
ligar:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xed in position 12: ordinal not in range(128)
Esta é a linha 222 emprettytable.py
. Usaunicode
, que é a fonte dos meus problemas, e não apenas neste script, mas em outros scripts do Python que escrevi.
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]))
Por favor, me diga o que estou fazendo de errado aqui. Como posso fazerunicode
trabalhar sem hackingprettytable.py
ou alguma das outras bibliotecas que eu uso? Existe mesmo uma maneira de fazer isso?
EDIT: O erro ocorre não noprint
declaração, mas not.add_row
ligar.
EDIT: Com a ajuda de Bastien Léonard, surgiu a solução a seguir. Não é uma panacéia, mas funciona.
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')
Eu acabei tendo que decodificar o caminho e codificar na saída. Tudo isso me deixa esperançoso de que todos portem suas bibliotecas para o Python 3.x mais cedo ou mais tarde!