切换到 Python 3 导致 UnicodeDecodeError

Posted

技术标签:

【中文标题】切换到 Python 3 导致 UnicodeDecodeError【英文标题】:Switching to Python 3 causing UnicodeDecodeError 【发布时间】:2014-07-18 00:53:46 【问题描述】:

我刚刚在 Sublime 中添加了 Python3 解释器,以下代码停止工作:

for directory in directoryList:
    fileList = os.listdir(directory)
    for filename in fileList:
        filename = os.path.join(directory, filename)
        currentFile = open(filename, 'rt')
        for line in currentFile:               ##Here comes the exception.
            currentLine = line.split(' ')
            for word in currentLine:
                if word.lower() not in bigBagOfWords:
                    bigBagOfWords.append(word.lower())
        currentFile.close()

我收到以下异常:

  File "/Users/Kuba/Desktop/DictionaryCreator.py", line 11, in <module>
    for line in currentFile:
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/encodings/ascii.py", line 26, in decode
    return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xcc in position 305: ordinal not in range(128)

我觉得这很奇怪,因为据我所知 Python3 应该在任何地方都支持 utf-8。更重要的是,相同的代码在 Python2.7 上没有问题。我已经阅读了有关添加环境变量PYTHONIOENCODING 的信息,但我尝试了它 - 无济于事(但是,在 OS X Mavericks 中添加环境变量似乎并不容易,所以也许我在添加变量时做错了? 我修改了/etc/launchd.conf)

【问题讨论】:

请务必包含您的异常的完整回溯。 【参考方案1】:

总的来说,我找到了 3 种方法来修复 Python3 中与 Unicode 相关的错误:

    明确使用编码,如 currentFile = open(filename, 'rt',encoding='utf-8')

    由于字节没有编码,因此在写入文件之前将字符串数据转换为字节,如 data = 'string'.encode('utf-8')

    特别是在 Linux 环境下,检查 $LANG。当 LANG=C 将默认编码设置为“ascii”而不是“utf-8”时,通常会出现此类问题。可以将其更改为其他适当的值,例如 LANG='en_IN'

【讨论】:

【参考方案2】:

Python 3 在读取时解码文本文件,在写入时编码。默认编码取自locale.getpreferredencoding(False),显然对于您的设置返回'ASCII'。见open() function documenation:

在文本模式下,如果未指定 encoding,则使用的编码取决于平台:调用locale.getpreferredencoding(False) 以获取当前的语言环境编码。

您应该使用显式编解码器打开文本文件,而不是依赖系统设置:

currentFile = open(filename, 'rt', encoding='latin1')

您设置encoding 参数以匹配您正在阅读的文件。

Python 3 支持 UTF-8 作为源代码的默认值。

这同样适用于写入可写文本文件;写入的数据将被编码,如果您依赖系统编码,除非您明确设置合适的编解码器,否则您可能会得到UnicodeEncodingError 异常。编写时使用什么编解码器取决于您正在编写的文本以及您之后计划对文件执行的操作。

您可能想在Unicode HOWTO 中阅读有关 Python 3 和 Unicode 的内容,其中解释了源代码编码以及读写 Unicode 数据。

【讨论】:

嗯,它确实有效。当我在打开时将编码更改为“utf-8”时,它不会再次运行。这样好吗? 现在清除,谢谢。因此,只有源代码应始终为 utf-8。 @Byakuya:是的,源代码默认使用 UTF-8;您可以使用# codec: .. 注释作为第一行或第二行来指示源文件的不同编码。 @JIXIang:你可以在启动 Python 之前将你的语言环境设置为 UTF-8。但是,无论如何,我发现明确设置编码是谨慎的。显式优于隐式。 @Anon:你说 Python 3.4 然后链接到 Python 3.7 源代码;我认为您的意思是从 3.4 开始有一个简化的后备。见bugs.python.org/issue9548。 OSX 的后备版本是much further back,是 Python 3.0 的一部分(后来被向后移植到 Python 2.7)。仅当 LANG 设置为无效值时才使用回退。【参考方案3】:

“据我所知,Python3 应该在任何地方都支持 utf-8 ...” 不对。我有 python 3.6,我的默认编码不是 utf-8。 要在我的代码中将其更改为 utf-8,我使用:

import locale
def getpreferredencoding(do_setlocale = True):
   return "utf-8"
locale.getpreferredencoding = getpreferredencoding

如中所述 Changing the “locale preferred encoding” in Python 3 in Windows

【讨论】:

以上是关于切换到 Python 3 导致 UnicodeDecodeError的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Windows 上将 Python 3.8 切换到 Python 3.6 作为默认值?

git切换分支导致代码丢失找回(git reflog找回错误的重置)

从OpenCV 3切换到OpenCV 4会导致网络摄像头以最高5帧的速度记录,而不是通常的30帧。

使用jupyter切换子环境,以及导致的`找不到指定模块`和`找不到指定的程序`问题

pip install报错是啥问题啊?

linux(centos6.8)python2如何切换到3?