【问题标题】:Why is Python trying to automatically encode my Unicode string? [duplicate]为什么 Python 试图自动编码我的 Unicode 字符串? [复制]
【发布时间】:2023-03-27 23:35:01
【问题描述】:

我正在尝试从以 ISO-8859-1 编码的文件中读取一堆电子邮件,然后将它们(部分)写入使用 UTF-8 编码的 JSON 文件。我目前有一个程序可以读取它们并生成具有str 类型属性的对象,其中包含消息的各个字段。我想将这些 str 字符串(编码位字符串)转换为 unicode 字符串(抽象 Unicode 对象),以便以后在写出文件时可以使用 UTF-8 重新编码它们。所以我使用strdecode方法,像这样:

msg_dict = {u'Id' : message.message_id.decode('iso-8859-1'), 
                u'Subject' : message.subject.decode('iso-8859-1'), 
                u'SenderEmail' : message.sender_email.decode('iso-8859-1'),
                u'SenderName' : message.sender_name.decode('iso-8859-1'),
                u'Date': message.date.isoformat()}

根据我阅读的文档,decode 应该采用str 对象,根据给定的编码解释其字节,并返回代表这些字符的unicode 对象。但是当我运行我的代码时,我得到了这个错误:

  File "/home/edward/long/path/omitted/dumpMails.py", line 38, in <module>
    u'Subject' : message.subject.decode('iso-8859-1'),
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 1: ordinal not in range(128)

当我调用 decode 时,我怎么会收到 encode 错误?我最好的猜测是 Python 已决定使用默认编码自动将返回的 unicode 转换回 str。但它为什么要这样做呢?将unicodes 放入字典有什么关系吗?

【问题讨论】:

    标签: python string python-2.7 unicode


    【解决方案1】:

    Python 将自动尝试并编码一个值如果它还不是字节字符串。毕竟,您无法解码 Unicode 字符串,因此 Python 尝试提供帮助并尝试使其成为字节字符串 first

    换句话说,字符串已经解码为 un​​icode

    >>> decoded = u'åüøî'
    >>> decoded.decode('latin1')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)
    

    你要么必须测试它是否已经是一个 Unicode 字符串,或者它是否总是一个 Unicode 字符串,只是不要尝试解码它。

    顺便说一句,如果您有一个要编码的字节字符串,您将看到相反的问题; Python 将首先隐式解码这样的值,以便它有一个 unicode 对象为您编码:

    >>> encoded = u'åüøî'.encode('utf8')
    >>> encoded.encode('latin1')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)
    

    注意该错误消息中的 decode 关键字。

    【讨论】:

    • 你说得对,我猜生成message 对象(我没有写)的代码文档对subject 属性的类型撒了谎。这就是我讨厌鸭子类型语言的原因:直到运行时我才知道subjectstr 还是unicode,如果我猜错了它仍然会尝试将变量用作错误的类型。
    • @Edward:您可以随时使用isinstance(obj, str) 来查看是否需要先解码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-26
    • 2018-01-13
    • 2021-04-10
    • 1970-01-01
    • 1970-01-01
    • 2014-12-05
    • 1970-01-01
    相关资源
    最近更新 更多