Python编码 - 无法解码为utf8
我有一个sqlite数据库,它是由一个外部程序填充的。我想用python读取里面的数据,但每次尝试读取时都会出现一个错误:
操作错误:无法解码为UTF-8
如果我用sqlite管理工具打开数据库,查看那些出问题的记录,数据看起来没问题。但是当我把表导出为csv格式时,我发现那些出问题的记录里的字符£变成了£
当我在python中读取这个csv文件时,那些出问题的记录里的£依然显示为£,不过这对我来说没关系,我可以手动处理。但是我希望能直接从数据库中读取数据,而不需要先转换成csv。
我在网上查了一些类似问题的答案,目前我尝试过把“text_factory”设置为“str”,还尝试过用sqlite管理工具把列的数据类型从TEXT改为BLOB,但还是出现这个错误。
我下面的代码运行后也出现了操作错误:无法解码为UTF-8
conn = sqlite3.connect('test.db')
conn.text_factory = str
curr = conn.cursor()
curr.execute('''SELECT xml_dump FROM hands_1 LIMIT 5000 , 5001''')
row = curr.fetchone()
数据库中所有超过5000的记录都有这个字符问题,因此会产生错误。
任何帮助都非常感谢。
2 个回答
如果数据库里的文本大部分是用UTF-8编码的,但你还是遇到了这个错误(无法解码为UTF-8),那么问题可能出在某些行的数据不合法,不符合UTF-8的标准。默认情况下,Python的decode()
函数在遇到这种文本时会抛出一个异常。如果你碰到这种情况,想要简单地忽略这些错误,可以像下面这样设置一个text_factory
:
conn = sqlite3.connect('my-database.db')
conn.text_factory = lambda b: b.decode(errors = 'ignore')
Python试图通过将存储在数据库中的字节文本转换成python的str
对象来帮助你。为了完成这个转换,Python需要猜测你查询返回的每个字节(或字节组)代表哪个字母。默认情况下,它使用一种叫做utf-8的编码来进行猜测。显然,在你的情况下,这个猜测是错误的。
解决办法是给Python一点提示,告诉它如何将字节映射到字母(也就是unicode字符)。你已经接近这个解决方案,使用了以下代码:
conn.text_factory = str
不过(根据你在上面评论中的回复),因为你使用的是Python 3,str
是默认的文本工厂,所以那行代码对你来说不会有什么新效果(可以查看文档)。
这行代码背后发生的事情是,Python尝试使用str
函数将查询返回的字节转换成字符串,类似于:
your_string = str(the_bytes, 'utf-8') # actually uses `conn.text_factory`, not `str`
...但是你想要的是一种不同的编码,替换掉'utf-8'。由于你不能改变str
函数的默认编码,你需要用其他方式来模拟这个过程。你可以使用一个一次性的不带名字的函数,叫做lambda,来实现:
conn.text_factory = lambda x: str(x, 'latin1')
现在,当数据库将字节传递给Python时,Python会尝试使用'latin1'编码来将它们映射为字母,而不是使用'utf-8'编码。当然,我不知道'latin1'是否是你数据的正确编码。实际上,你可能需要尝试几种编码来找到合适的。我建议你先试试以下几种:
'iso-8859-1'
'utf-16'
'utf-32'
'latin1'
你可以在这里找到更完整的编码列表。
另一种选择是让从数据库中出来的字节保持字节格式。是否这样做对你有好处,取决于你的应用场景。你可以通过设置:
conn.text_factory = bytes