我有一个由外部程序填充的 sqlite 数据库。我试图用 python 读取数据。当我尝试读取数据时出现以下错误:
OperationalError:无法解码为 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条以上的记录都存在这个字符问题,所以报错。
感谢任何帮助。
最佳答案
Python 试图通过将文本片段(在数据库中存储为字节)转换为 python str
对象来为您提供帮助。为了进行这种转换,python 必须猜测查询返回的每个字节(或字节组)代表什么字母。默认猜测是一种称为 utf-8 的编码。显然,这个猜测在你的情况下是错误的。
解决方案是给 python 一点提示,说明如何进行从字节到字母(即 unicode 字符)的映射。你已经接近这条线了
conn.text_factory = str
但是(根据您在上述评论中的回复),由于您使用的是 python 3,str
是默认 文本工厂,因此该行不会执行任何新操作为您服务(参见 the docs )。
这一行在幕后发生的事情是 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'
您可以找到更完整的列表 here .
另一种选择是简单地让从数据库中出来的字节保持为字节。这对您来说是否是个好主意取决于您的应用程序。您可以通过设置来做到这一点:
conn.text_factory = bytes
关于Python 编码 - 无法解码为 utf8,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23508153/