【问题标题】:UnicodeDecodeError only with cx_freezeUnicodeDecodeError 仅适用于 cx_freeze
【发布时间】:2011-05-06 20:34:11
【问题描述】:

我收到错误:"UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 7338: ordinal not in range(128)" 在我使用 cx_freeze 冻结脚本后尝试运行程序。如果我正常运行 Python 3 脚本,它运行良好,但只有在我冻结它并尝试运行可执行文件之后,它才会给我这个错误。我会发布我的代码,但我不确切知道要发布哪些部分,所以如果有任何某些部分可以帮助我知道,我会发布它们,否则我似乎曾经遇到过这个问题并解决了它,但是已经有一段时间了,我不记得究竟是什么问题或我是如何解决它的,所以任何帮助或指示让我朝着正确的方向前进都会有很大帮助。提前致谢。

【问题讨论】:

    标签: python encoding python-3.x cx-freeze


    【解决方案1】:

    告诉我们具体平台上的 Python 版本。

    显示发生错误时获得的完整回溯。你自己看看吧。出现的代码的最后一行是什么?你认为被解码的bytes 字符串是什么?为什么要使用ascii 编解码器??

    请注意,使用默认编解码器(例如 ascii)将 bytes 自动转换为 str 不是由 Python 3.x 完成的。所以要么你明确地这样做,要么 cx_freeze 是。

    更新在 cmets 中获得更多信息。

    Excel 不以 ASCII 格式保存 csv 文件。它将它们保存在 MS 所称的“ANSI 代码页”中,该代码页因区域设置而异。如果你不知道你的是什么,那可能是cp1252。要检查,请执行以下操作:

    >>> import locale; print(locale.getpreferredencoding())
    cp1252
    

    如果 Excel 确实以 ASCII 格式保存文件,那么您有问题的 '\xa0' 字节将被替换为“?”并且您不会收到 UnicodeDecodeError。

    将您的文件保存在UTF-8 中需要您使用encoding='utf8' 打开您的文件,并且会遇到同样的问题(除了您会抱怨 0xc2 而不是 0xa0)。

    您无需将所有四个 csv 文件都发布到网络上。只需运行这个小脚本(未经测试):

    import sys
    for filename in sys.argv[1:]:
        for lino, line in enumerate(open(filename), 1):
            if '\xa0' in line:
                print(ascii(filename), lino, ascii(line))
    

    '\xa0'NO-BREAK SPACE 又名   ...您可能需要编辑文件以将其更改为普通空格。

    您可能需要在 cx_freeze 邮件列表中询问以了解为什么会发生此错误。他们会想知道完整的回溯。进行一些练习——在这里展示一下。

    顺便说一句,“偏移量 7338”相当大——您是否希望 csv 文件中有这么长的行?也许有些东西正在读取您的所有文件...

    【讨论】:

    • 我在 Windows 上使用 python v3.1,在 bot x86 和 64 上尝试过。我会向您展示完整的回溯。我的代码在堆栈上的最后一次调用是用于从 csv 文件中获取我的数据的 for 循环:'for row in DataReader:'。我不确定为什么要使用 ascii 编解码器,我没有明确使用它,我尝试在记事本中打开 2 个问题文件并将编码更改为 UTF-8 并重新保存,因为可能 excel 保存在 ascii 编码中,仍然没有帮助。所以我猜这让 cx_freeze 使用 ascii,如果问题仅在我冻结脚本后出现,这是有道理的。那么我该如何解决呢?
    • @Brock S.:编辑您的问题,而不是在 cmets 中添加新信息。 显示完整的回溯。显示您是如何打开输入文件的。
    • 这很棒!一个文件中有 2 行在其中一个单元格的末尾有一个 &nbsp,另一个文件中有 1 行使用 &nbsp 而不是空格。我需要做的就是摆脱这些字符并用常规空格替换一个。这真的让我很困惑,为什么我现在才得到这个错误。我以前使用过这些文件和冻结的脚本,就像我现在使用它一样。我想我会像你建议的那样在 cx_freeze 邮件列表中询问,也许会看到为什么这个错误只出现在这一次。感谢您的帮助。
    【解决方案2】:

    该错误本身表明您在 python 字符串中有一个字符不是普通的 ASCII 字符:

    >>> b'abc\xa0'.decode('ascii')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 3: ordinal not in range(128)
    

    我当然不知道为什么这只会在脚本被冻结时发生。您可以将整个脚本包装在 try/except 中,然后手动打印出全部或部分有问题的字符串。

    编辑:这可能是这样的

    try:
        # ... your script here
    except UnicodeDecodeError as e:
        print("Exception happened in string '...%s...'"%(e.object[e.start-50:e.start+51],))
        raise
    

    【讨论】:

    • OK 更新问题并提供更多信息。问题出现在“for row in DataReader:”行中,DataReader 是一个 csv 读取器对象。因此,为了增加这个错误仅在我冻结后发生的奇怪效果,它也只发生在我在程序开始时读取数据的 4 个文件中的前 2 个文件中。我将每个 for 循环包装在 try/except 中,当错误发生时它发生在开头,因此它没有从 csv 文件中提取任何数据。有任何想法吗?如果您能告诉我前 2 个和后 2 个之间的区别以产生错误,我可以以某种方式发布所有 4 个 csv 文件。
    • 您需要打印出导致混乱的字符串部分,以便找出原因(请参阅上面答案中的最新编辑)。如果不清楚发生了什么以及原因,请尝试在脚本处理非冻结版本中同一字符串的相同部分时对其进行调试,并检查字符串本身是否具有不同的字符,或者发生了其他事情。
    【解决方案3】:

    通过设置默认编码修复:

    reload(sys)
    sys.setdefaultencoding("utf-8")
    

    【讨论】:

    • 来自sys.setdefaultencoding 上的 Python 文档:“此函数仅供站点模块实现使用,并在需要时由 sitecustomize 使用。”
    【解决方案4】:

    对该行使用str.decode() 函数。您还可以指定编码,如myString.decode('cp1252')

    另请看:http://docs.python.org/release/3.0.1/howto/unicode.html#unicode-howto

    【讨论】:

    • 普通的 \xa0 本身也不是有效的 UTF-8,它很可能是 ISO 8859-1 或 Windows-1252。
    • @Adam Rosenfield:他在 Windows 上,正在读取 Excel“另存为 CSV”的结果。 ISO 8859-1 的机会是
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多