如何解决 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__ 的解决方法