【问题标题】:Python + PostgreSQL + strange ascii = UTF8 encoding errorPython + PostgreSQL + 奇怪的 ascii = UTF8 编码错误
【发布时间】:2010-06-07 17:22:16
【问题描述】:

我有包含字符 "\x80" 的 ascii 字符串来表示欧元符号:

>>> 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)

【问题讨论】:

  • 您必须从当前语言环境(\x80 == )对其进行 .decode(),然后 .encode("utf-8")
  • 如果你有一个 ASCII 字符串,你就没有 "\x80"。相反,如果你有 "\x80",你就没有 ASCII 字符串。
  • @Thanatos:是的。正如我所说,我是一个字符编码新手,我不知道还能叫什么。我只是说前面没有“u”的python字符串文字。

标签: python postgresql unicode encoding utf-8


【解决方案1】:

问题从一个错误的前提开始:

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

ASCII 字符在 "\x00" 到 "\x7F" 范围内。

先前接受的现在已删除的答案在两个严重误解下运行 (1) 区域设置 == 编码 (2) latin1 编码将“\x80”映射到欧元字符。 p>

事实上,所有 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 编码:文件是在哪里(地理位置)创建的?文本是用什么语言写的?除了假定的欧元值>“\x7f”的任何字符吗?如果是这样,它们在哪些和什么上下文中使用?

更新 2 如果您不“知道程序是如何编写的”,您和我们都无法就它是否总是使用“\x80”作为欧​​元字符形成意见。虽然不这样做会非常愚蠢,但不能排除。

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

【讨论】:

  • +1 表示“您需要知道您的数据采用什么编码方式。”你需要知道。 +1 表示“latin1 [不映射] '\x80' 到欧元”。 +1 用于找到我仍在寻找的真正编码。
  • @Thanatos: "real encoding": cp125x 是常见的嫌疑犯。
  • 是的,我绝对是 cp125x 的一员,所以它可以在我给定的计算机上运行。我会改为硬编码。接受的答案是正确的,除了在这种情况下使用“latin1”,是吗?
  • @Claudiu:(1)我不明白你对“so”这个词的使用。 (2) 不,目前接受的答案充满了混乱和错误。
  • @John:我的意思是它恰好在我的机器上工作。也许这纯粹是机会。我正在从文件中读取这些数据,例如open(fname).read()。它包含带有\x80 的字符串,代表欧元字符。它只是一个纯文本文件。它是由另一个程序生成的,但我不知道它是如何生成文本的。什么是好的解决方案?我想我可以假设它为欧元字符输出"\x80",这意味着我可以假设它是用具有该字符作为欧元的 cp125x 编码的。
猜你喜欢
  • 1970-01-01
  • 2011-08-17
  • 2012-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-13
  • 1970-01-01
相关资源
最近更新 更多