Python + PostgreSQL +奇怪的ascii = UTF8编码错误

时间:2010-06-07 17:22:17

标签: python postgresql unicode encoding utf-8

我有ascii字符串,其中包含代表欧元符号的字符"\x80"

>>> print "\x80"
€

将包含此字符的字符串数据插入数据库时​​,我得到:

psycopg2.DataError: invalid byte sequence for encoding "UTF8": 0x80
HINT:  This error can also happen if the byte sequence does not match the encodi
ng expected by the server, which is controlled by "client_encoding".

我是一个unicode新手。如何将包含"\x80"的字符串转换为包含相同欧元符号的有效UTF-8?我尝试在各种字符串上调用.encode.decode,但遇到错误:

>>> "\x80".encode("utf-8")
Traceback (most recent call last):
  File "<pyshell#14>", line 1, in <module>
    "\x80".encode("utf-8")
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0: ordinal not in range(128)

1 个答案:

答案 0 :(得分:12)

问题始于错误的前提:

  

我有ascii字符串,其中包含字符“\ x80”来表示欧元符号。

ASCII字符在“\ x00”到“\ x7F”的范围内。

先前已接受的已删除答案在两次严重误解下运作(1)locale == encoding(2)latin1编码将“\ x80”映射为欧元字符。

实际上,所有ISO-8859-x编码都将“\ x80”映射到U + 0080,这是C1控制字符之一,而不是欧元字符。这些编码中只有3个(x in(7,15,16))提供欧元字符,如“\ xA4”。请参阅this Wikipedia article

您需要知道您的数据所处的编码。它创建了什么机器?怎么样?它创建的区域设置(不一定是你的)可能会给你一个线索。

请注意,“我的数据以latin1编码”在那里有“邮件中的支票”和“我当然会在早上爱你”。您的数据可能采用Windows平台上的cp125x编码之一进行编码。请注意,除了cp1251(Windows Cyrillic)之外的所有这些都将“\ x80”映射到欧元字符:

>>> ['\x80'.decode('cp125' + str(x), 'replace') for x in range(9)]
[u'\u20ac', u'\u0402', u'\u20ac', u'\u20ac', u'\u20ac', u'\u20ac', u'\u20ac', u'\u20ac', u'\u20ac']

更新以回应OP的评论

  

我正在从文件中读取此数据,例如open(fname).read()。它包含带有\ x80的字符串,表示欧元字符。它只是一个纯文本文件。它是由另一个程序生成的,但我不知道如何生成文本。什么是一个好的解决方案?我想我可以假设它为一个欧元字符输出“\ x80”,这意味着我可以假设它是用cp125x编码的,它具有该字符作为欧元。

这有点令人困惑:首先你说

  

它包含带有\ x80的字符串,表示欧元字符

但后来你说

  

我想我可以假设它为欧元字符输出“\ x80”

请解释。

选择合适的cp125x编码:创建文件的位置(地理位置)?用什么语言写的是文字?除推定的欧元以外的任何字符,其值> “\ 0x7F部分”?如果是这样,他们使用了哪些以及它们的上下文?

更新2 如果您“不知道该程序是如何编写的”,那么您和我们都不能就是否始终使用“\ x80”表示欧元字符。虽然这样做会带来巨大的愚蠢,但不能排除它。

如果文本是用英文写的和/或是在美国写的,和/或是在Windows平台上写的,那么可以合理地确定cp1252是要走的路......直到你得到相反的证据,在这种情况下,你需要自己猜测编码或回答(什么语言,什么地方)问题。