【发布时间】:2009-07-20 20:52:20
【问题描述】:
我有一个 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 范围的字符。我有时会在prettytable.pyc 的第222 行收到这样的错误消息,当它到达t.add_row 调用时:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xed in position 12: ordinal not in range(128)
这是prettytable.py 中的第 222 行。它使用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 或我使用的任何其他库?有没有办法做到这一点?
编辑:错误不在print 语句中,而是在t.add_row 调用中。
编辑:在 Bastien Léonard 的帮助下,我想出了以下解决方案。它不是灵丹妙药,但它确实有效。
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!
【问题讨论】: