繁体   English   中英

Python3 utf-8解码问题

[英]Python3 utf-8 decode issue

以下代码在我的Windows机器上使用Python3运行正常并打印字符'é':

data = b"\xc3\xa9"

print(data.decode('utf-8'))

但是,在基于Ubuntu的docker容器上运行相同会导致:

UnicodeEncodeError: 'ascii' codec can't encode character '\xe9' in position 0: ordinal not in range(128)

有什么必须安装才能启用utf-8解码吗?

问题在于print()表达式,而不是decode()方法。 如果你仔细一看,出现的异常是Unicode codeError,而不是一个- codeError。

每当你使用print()函数时,Python都会将其参数转换为str ,然后将结果编码为bytes ,这些bytes将被发送到终端(或运行的任何Python)。 用于编码的编解码器(例如UTF-8或ASCII)取决于环境。 在一个理想的情况下,

  • Python使用的编解码器与终端所期望的编解码器兼容,因此字符显示正确(否则你会得到像“é”而不是“é”的mojibake);
  • 使用的编解码器涵盖了一系列足以满足您需求的字符(例如UTF-8或UTF-16,它们包含所有字符)。

在您的情况下,您提到的Linux docker不符合第二个条件:使用的编码是ASCII,它只支持旧英文打字机上的字符。 这些是解决此问题的几个选项:

  • 设置环境变量:在Linux上,Python的编码默认值取决于此(至少部分)。 根据我的经验,这是一个试验和错误; LC_ALL设置为包含“UTF-8”的东西曾经为我工作过一次。 您必须将它们放在终端运行的shell的启动脚本中,例如。 .bashrc
  • 重新编码STDOUT,如下所示:

     sys.stdout = open(sys.stdout.buffer.fileno(), 'w', encoding='utf8') 

    使用的编码必须匹配终端之一。

  • 自己编码字符串并将它们发送到sys.stdout底层的二进制缓冲区,例如。 sys.stdout.buffer.write("é".encode('utf8')) 这当然是比print("é")更多的样板。 同样,使用的编码必须匹配终端之一。
  • 完全避免print() 使用open(fn, encoding=...)作为输出,进度信息的日志记录模块 - 取决于脚本的交互方式,这可能是值得的(诚然,在写入STDERR时可能会遇到相同的编码问题)记录模块)。

可能还有其他选择,但我怀疑有更好的选择。

似乎ubuntu - 取决于版本 - 使用一个或另一个编码作为默认值,它也可能在shell和python之间有所不同。 通过这个帖子这个博客

因此推荐的方法似乎是告诉你的python实例使用utf-8作为默认编码:

通过环境变量设置python源文件的默认编码:

export PYTHONIOENCODING=utf8

此外,在源文件中,您可以声明您希望显式使用的编码,因此无论环境设置如何,它都应该工作(请参阅此问题+答案python文档PEP 263

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
....

关于python读取的文件编码的解释,您可以在open命令中明确指定它

with open(fname, "rt", encoding="utf-8") as f:
    ...

并且有一些更具有一些副作用的hackish方式,但是每次都会保存你以明确指定它

import sys
# sys.setdefaultencoding() does not exist, here!
reload(sys)  # Reload does the trick!
sys.setdefaultencoding('UTF8')

请在相关的答案和评论中阅读有关此黑客的警告。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM