我有一个Python 2.6脚本,它使用拉丁文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
Run Code Online (Sandbox Code Playgroud)
但该Name列可以包含超出ASCII范围的字符.prettytable.pyc当它进入t.add_row调用时,我有时会在第222行收到类似这样的错误消息:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xed in position 12: ordinal not in range(128)
Run Code Online (Sandbox Code Playgroud)
这是第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]))
Run Code Online (Sandbox Code Playgroud)
请告诉我这里我做错了什么.如何在unicode没有黑客攻击prettytable.py或我使用的任何其他库的情况下开展工作?有没有办法做到这一点?
编辑:错误不是出现在print语句中,而是出现在t.add_row调用中.
编辑:在BastienLé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')
Run Code Online (Sandbox Code Playgroud)
我最终不得不在路上进行解码并在出路时进行编码.所有这些让我充满希望,每个人都可以将他们的库尽快移植到Python 3.x!
在模块的开头添加:
# coding: latin1
Run Code Online (Sandbox Code Playgroud)
或者自己将字符串解码为Unicode.
[编辑]
自从我使用Unicode以来已经有一段时间了,但希望此示例将展示如何将Latin1转换为Unicode:
>>> s = u'ééé'.encode('latin1') # a string you may get from the database
>>> s.decode('latin1')
u'\xe9\xe9\xe9'
Run Code Online (Sandbox Code Playgroud)
[编辑]
文档:
http://docs.python.org/howto/unicode.html
http://docs.python.org/library/codecs.html