仅在cx_freeze中出现UnicodeDecodeError

2 投票
4 回答
2189 浏览
提问于 2025-04-16 17:09

我在用cx_freeze把我的脚本打包成可执行文件后,运行程序时遇到了一个错误:"UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 7338: ordinal not in range(128)"。如果我直接运行这个Python 3脚本,它是可以正常工作的,但一旦我把它打包成可执行文件后再运行,就会出现这个错误。我想发我的代码,但我不太确定该发哪些部分。如果你们知道哪些部分能帮到我,请告诉我,我会发上来。其实我之前也遇到过这个问题并解决了,但时间久了我忘了具体是什么问题,也不记得我是怎么解决的,所以任何帮助或建议都非常感谢!

4 个回答

2

通过设置默认编码来修复:

reload(sys)
sys.setdefaultencoding("utf-8")
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
2

请告诉我们你使用的Python版本和平台。

展示一下你在出错时看到的完整错误信息。自己看看,最后一行代码是什么?你觉得正在被解码的bytes字符串是什么?为什么会使用ascii编码呢?

要注意,Python 3.x并不会自动把bytes转换成str,也就是说,它不会用默认的编码(比如ascii)来做这个转换。所以,要么是你自己在做这个转换,要么是cx_freeze在做。

更新:根据评论中的进一步信息。

Excel保存的csv文件并不是用ASCII格式的,而是用微软称之为“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'是一个不可断行空格,也就是&nbsp;……你可能需要编辑你的文件,把这些改成普通空格。

可能你需要在cx_freeze的邮件列表上询问,看看为什么会出现这个错误。他们会想知道完整的错误信息。多练习一下——把它展示在这里。

顺便说一下,“偏移量7338”这个数字挺大的——你期待你的csv文件里有这么长的行吗?也许有什么东西在读取你整个文件……

撰写回答