如何解决 Python 3.6 中的 UnicodeDecodeError?

Posted

技术标签:

【中文标题】如何解决 Python 3.6 中的 UnicodeDecodeError?【英文标题】:How to solve UnicodeDecodeError in Python 3.6? 【发布时间】:2018-12-04 04:43:34 【问题描述】:

我从 Python 2.7 切换到 Python 3.6。

我有处理一些非英语内容的脚本。

我通常通过 Cron 和终端运行脚本。

我的 Python 2.7 脚本中有 UnicodeDecodeError,我通过这个解决了。

# encoding=utf8  
import sys  

reload(sys)  
sys.setdefaultencoding('utf8')

现在在 Python 3.6 中,它不起作用。我有像print("Here %s" % (myvar)) 这样的打印语句,它会引发错误。我可以通过将其替换为myvar.encode("utf-8") 来解决此问题,但我不想写每个打印语句。

我在终端中执行了PYTHONIOENCODING=utf-8,但仍然存在这个问题。

有没有更简洁的方法来解决 Python 3.6 中的UnicodeDecodeError 问题?

有没有办法告诉 Python3 以 utf-8 格式打印所有内容?就像我在 Python2 中所做的那样?

【问题讨论】:

非英文文件本身是否以 UTF-8 正确编码? @EdwardMinnix 我正在从各种 Hewbrew/Korean 站点抓取数据,因此数据并不总是干净的。 @usr2564301 有没有办法告诉 Python3 以 utf-8 打印所有内容?就像我在 Python2 中所做的那样? 通常您的终端定义了一个编码,Python 使用该编码来设置其文件对象的编码 (sys.stdout)。你能提供你机器上sys.stdout.encoding 的设置吗? 我认为这是问题的根源。你用的是什么奇怪的终端?在 Unix-ish 环境中,您可以将 env var TERM 设置为 xterm 或类似的东西。 LANG 变量也可能会产生影响。 【参考方案1】:

听起来您的语言环境已损坏并且还有另一个字节->Unicode 问题。您为 Python 2.7 所做的事情只是掩盖了真正的问题(这是您必须reload sys 才能使其工作的原因)。

要修复您的语言环境,请尝试从命令行输入locale。它应该类似于:

LANG=en_GB.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_GB.UTF-8"
LC_TIME="en_GB.UTF-8"
LC_COLLATE="en_GB.UTF-8"
LC_MONETARY="en_GB.UTF-8"
LC_MESSAGES="en_GB.UTF-8"
LC_ALL=

locale 取决于 LANG 是否正确设置。 Python 有效地使用locale 来确定在写入标准输出时使用什么编码。如果无法解决,则默认为 ASCII。

您应该首先尝试修复您的语言环境。如果出现locale 错误,请确保您安装了适合您所在地区的正确语言包。

如果所有其他方法都失败了,您始终可以通过设置 PYTHONIOENCODING=UTF-8 来修复 Python。这应该作为最后的手段,因为您将再次掩盖问题。

如果 Python 在设置 PYTHONIOENCODING 后仍然抛出错误,请使用堆栈跟踪更新您的问题。您可能正在进行隐含的转换。

【讨论】:

对于未来的读者,请参阅我们在聊天中的对话@Alastair McCormack 如何帮助我解决我的问题。 chat.***.com/rooms/173761/… 感谢聊天中的回答和讨论,这对我很有帮助。我在 python3 中执行 print('\u25cf') 时遇到了类似的错误。将语言环境设置为 en_US.utf8 很有帮助。【参考方案2】:

我在基于 Ubuntu 18.04 的 Docker 容器中使用 Python 时遇到了这个问题。 这似乎是一个语言环境问题,通过在 Dockerfile 中添加以下内容解决了这个问题:

ENV LANG C.UTF-8

【讨论】:

export LANG=en_GB.UTF-8 在控制台中运行 python 之前暂时修复此问题【参考方案3】:

对于使用 pickle 加载以前保存在 python 2 中的文件并遇到 UnicodeDecodeError 的每个人,请尝试设置 pickle encoding 参数:

with open("./data.pkl", "rb") as data_file:
    samples = pickle.load(data_file, encoding='latin1')

【讨论】:

【参考方案4】:

对于纯 Python 解决方案,您必须重新创建 sys.stdout 对象:

import sys, codecs
sys.stdout = codecs.getwriter('utf-8')(sys.stdout.detach())

在此之后,一个普通的print("hello world") 应该被自动编码为 UTF-8。

但是您应该尝试找出为什么您的终端设置为如此奇怪的编码(Python 只是试图采用这种编码)。也许您的操作系统配置错误。

编辑:在我的测试中,取消设置 env 变量 LANG 为我的 stdout 编码产生了这个奇怪的设置:

LANG= python3
import sys
sys.stdout.encoding

打印'ANSI_X3.4-1968'

所以我猜你可能想将LANG 设置为类似 en_US.UTF-8。您的终端程序似乎没有这样做。

【讨论】:

这是否与sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf8') 相同或显着不同? (我确信我已经从这个网站学到了这一点。) @usr2564301 我不确定区别(如果有的话)。这个想法显然是一样的。一个更好的方法是简单的sys.stdout.encoding = 'utf-8',但不幸的是,这不起作用,因为encoding 字段是只读的。但这始终是思想之父,两种解决方案只是它的不同解决方法实现。【参考方案5】:

Python 3(包括 3.6)已经支持 Unicode。这是文档 - https://docs.python.org/3/howto/unicode.html

因此您不需要像 Python 2.7 那样强制支持 Unicode。尝试正常运行您的代码。如果您在读取 ​​Unicode 文本文件时遇到任何错误,您需要在读取文件时使用 encoding='utf-8' 参数。

【讨论】:

我没有足够的声誉来评论和询问他的终端。顺便说一句,你已经放弃了很好的解决方案。【参考方案6】:

我的意思是你可以写一个这样的自定义函数: (我知道不是最优的)


import sys

def printUTF8(input):
    print(input.encode("utf-8"))

【讨论】:

有什么办法不用.encode("utf-8")?所以 Python 知道打印 utf-8 中的每个字符串?

以上是关于如何解决 Python 3.6 中的 UnicodeDecodeError?的主要内容,如果未能解决你的问题,请参考以下文章

如何提高 Python 3.6 中的 SQLite 插入性能?

如何使用scipy 1.0.0计算python 3.6中的VIF?

python3 unicod,utf-8,gbk的编码和解码中文显示问题

在 3.6 之前的 Python 版本中没有 __set_name__ 的解决方法

如何阻止不和谐机器人响应自身/所有其他机器人 [Python 3.6 中的不和谐机器人]

ubuntu python3.5升级3.6后打不开终端的解决办法