【问题标题】:Python UnicodeDecodeError - Am I misunderstanding encode?Python UnicodeDecodeError - 我误解了编码吗?
【发布时间】:2010-09-26 23:55:13
【问题描述】:

关于为什么这不起作用的任何想法?我真的认为“忽略”会做正确的事情。

>>> 'add \x93Monitoring\x93 to list '.encode('latin-1','ignore')
Traceback (most recent call last):
  File "<interactive input>", line 1, in ?
UnicodeDecodeError: 'ascii' codec can't decode byte 0x93 in position 4: ordinal not in range(128)

【问题讨论】:

标签: python unicode ascii encode


【解决方案1】:

神奇的线是:

unicodedata.normalize('NFKD', text).encode('utf-8', 'ignore')

在最需要的时候不会引发异常的一个衬垫(删除坏的 Unicode 字符...)

【讨论】:

    【解决方案2】:

    ……它们被称为“编码”是有原因的……

    前言:将 unicode 视为规范或理想状态。 Unicode 只是一个字符表。 №65 是拉丁文大写 A。№937 是希腊大写 omega。就是这样。

    为了让计算机存储和/或操作 Unicode,它必须将其 编码 为字节。 Unicode 最直接的编码是UCS-4;每个字符占用 4 个字节,所有 ~1000000 个字符都可用。这 4 个字节包含 Unicode 表中字符的编号,作为 4 字节整数。另一种非常有用的编码是 UTF-8,它可以将任何 Unicode 字符编码为一到四个字节。但也有一些有限的编码,如“latin1”,其中包含非常有限的字符范围,主要由西方国家使用。这样的编码每个字符只使用一个字节。

    基本上,Unicode 可以encoded 有多种编码,编码后的字符串可以解码 为 Unicode。问题是,Unicode 来得太晚了,所以我们这些使用 8 位 字符集 长大的人都太晚了,因为我们一直在使用 编码 字符串。编码可以是 ISO8859-1,或 windows CP437,或 CP850,或,或,或,取决于我们的系统默认值。

    因此,当您在源代码中输入字符串“add “Monitoring” to list”(我认为您想要字符串“add “Monitoring” to list”时,请注意第二个引号),您实际上是在使用已根据您系统的默认代码页编码的字符串(我假设您使用的是 Windows 代码页 1252,“Western”)。如果您想从中获取 Unicode,您需要从“cp1252”编码中解码字符串。

    所以,你的意思是:

    "add \x93Monitoring\x94 to list".decode("cp1252", "ignore")
    

    不幸的是,Python 2.x 也包含一个用于字符串的.encode 方法;这是“特殊”编码的便利功能,例如“zip”或“rot13”或“base64”编码,它们与 Unicode 无关。

    无论如何,在来回 Unicode 转换中,您只需要记住:

    • Unicode 字符串被编码为 Python 2.x 字符串(实际上是字节序列)
    • Python 2.x 字符串解码为 Unicode 字符串

    在这两种情况下,您都需要指定将使用的编码

    我不是很清楚,我困了,但我当然希望能帮上忙。

    PS 一个幽默的旁注:玛雅人没有 Unicode;古罗马人、古希腊人、古埃及人也没有。他们都有自己的“编码”,几乎不尊重其他文化。所有这些文明都化为灰烬。想想吧人!为了人类的利益,让您的应用程序支持 Unicode。 :)

    PS2 请不要说“但是中国人……”来破坏前面的信息。但是,如果您倾向于或有义务这样做,请考虑到 Unicode BMP 主要由中文表意文字填充,因此延迟它,因此中文是 Unicode 的基础。只要人们开发支持 Unicode 的应用程序,我就可以继续编造令人发指的谎言。干杯!

    【讨论】:

    • Unicode 不仅仅是一个字符表,例如,单个抽象字符可以由一系列代码点表示:拉丁大写字母 g,带有锐角(对应的编码字符 u"\u01F4" 或 '& #500;') 由序列 u"\u0047\u0301"(或 'Ǵ')表示。 is.gd/eTLi-
    • @J.F. Sebastian:不,Unicode 不仅仅是一个字符表。我只是为了这个答案的目的而过度简化了事情。
    • 另外,我相信 UTF-8 使用 1 到 6 个字节。可能有 2^32 个字符,但编码本身在跟踪多字节序列长度方面有一些开销。
    • @tchrist:我看不出你写的和我写的有什么不同。想指出你认为我“反过来”描述事物的确切位置吗?
    • @tchrist:在 2008 年,Python 3 比现在少得多,但我仍然注意到我的答案是关于 Python 2,尽管原始报告中报告的异常暗示了这一点问题。
    【解决方案3】:

    这似乎有效:

    'add \x93Monitoring\x93 to list '.decode('latin-1').encode('latin-1')
    

    这有什么问题吗?我想知道“忽略”、“替换”和其他此类编码错误处理何时出现?

    【讨论】:

    • 当你想编码一个包含在你选择的编码中无法表示的代码点的 unicode 字符串时,它就会出现,即 latin1 中的中文字符。然后,您可以指定编码应如何对此类代码点做出反应。
    • 如上所说,这无济于事。您正在通过一个函数,然后反过来。在最好的情况下,最终的字符串与原始字符串完全相同;在最坏的情况下,您会遇到 Heiko 概述的问题。
    • 似乎有效?? str_object.decode('latin1').encode('latin1') == str_object 适用于所有 STR 对象。换句话说,它什么都不做。
    • 它对 Latin-1 没有任何作用。对于任意字节序列并不总是有效的编码,或者具有相同字符的多个编码的编码,它是不同的。
    • 如果您必须手动操作encode 和/或decode,那么您做错了。
    【解决方案4】:

    encode 可用于 unicode 字符串,但您那里的字符串似乎不是 unicode(尝试使用 u'add \x93Monitoring\x93 to list ')

    >>> u'add \x93Monitoring\x93 to list '.encode('latin-1','ignore')
    'add \x93Monitoring\x93 to list '
    

    【讨论】:

    • 好吧,字符串是以非 unicode 的方式出现的。所以我需要对字符串做点什么。
    • 这意味着你得到的字符串已经被编码了。在下面的示例中,您只需再次解码和编码 - 假设是 latin-1 编码(这可能并不总是正确的)。我认为您可以简单地继续使用您的字符串,并让输出正确处理它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-06
    • 1970-01-01
    • 2023-03-26
    • 2013-08-20
    • 2018-05-05
    • 1970-01-01
    • 2015-02-03
    相关资源
    最近更新 更多