以 utf-8 格式将 unicode 字符打印到终端



我使用 Python 3.9.1 和 Linux (CentOS 7)。我想将 unicode 字符打印到控制台。我想用 UTF-8 做所有事情。如果我打开python交互式控制台并编写:

print("├")

一切顺利,它打印:

现在,我将相同的行print("├")放在文件中,然后使用 UTF-8 编码保存文件(Linux 上默认)。 然后我收到以下错误:

UnicodeEncodeError: 'latin-1' codec can't encode character 'u251c' in position 0: ordinal not in range(256)

"拉丁语-1"从何而来?

我还在第一行强制使用 UTF-8(无论如何这应该是 Python3 中的默认值)

# coding: utf8

但它不会改变任何东西。

有关哪些有效和哪些无效的更多信息:

s = "├"
#print(s) # FAIL
s2 = s.encode('utf8')
print(s2) # prints b'xe2x94x9c'
print(s2.decode('latin-1')) # prints the right thing

这是怎么回事?是否可以在脚本中获得与交互式控制台中相同的行为?

s = "├"(在 UTF-8 编码的源文件中)将字符u251C分配给 UTF-8 编码字符串s的第一个位置。

print(s)失败,因为此处打印绑定以将表示s的字节发送到标准输出,该输出需要latin-1编码。实际上,类似于s.encode('latin-1')的东西会失败,因为字符串中的第一个字符无法正确编码。

如果你真的运行该语句(s.encode('latin-1')),你会发现它会导致同样的错误。

s2 = s.encode('utf8')工作正常,它告诉 Python 将s的内容显式编码为字节序列。s2现在使用UTF-8编码来保存s的字节编码。(也许"b"会是一个更好的变量名,它毕竟不是一个字符串)

print(s2)确实打印b'xe2x94x9c',因为它只是打印字节序列的Python表示。它不是一个字符串,因此您可以获得打印值的表示形式。它应该是,它是你可以用来定义s2的文字,即s2 = b'xe2x94x9c'不会改变任何事情。

print(s2.decode('latin-1'))打印正确的东西有点神秘。s2是 U+251C 字符 (https://www.fileformat.info/info/unicode/char/251c/index.htm) 的正确 UTF-8 字节序列

显然,您的 Python 获取s2.decode('latin-1')的结果,再次将其编码为latin-1字节序列,然后将其写入输出流,在那里它为您正确呈现。

由于 Python 会对尝试打印 UTF-8 编码字符串的早期打印语句执行相同的操作,因此它解释了为什么这些语句无法正确显示(或根本不显示)。

解决方案是明确告诉 Python 将标准输出的编码覆盖为 UTF-8,这样您就可以打印 UTF-8 字符串,而无需 Python 尝试将其编码为latin-1编码字节序列(这将失败)。

如此处所述 https://docs.python.org/3/using/cmdline.html#envvar-PYTHONIOENCODING 您可以通过设置SET PYTHONENCODING=UTF-8.相反,如果要在交互式环境中复制问题,则可以通过PYTHONLEGACYWINDOWSSTDIO获得该行为。

何时何地设置此项取决于您的系统环境。其他应用程序是否依赖于较旧的脚本或其他版本的 Python 而不这样做?如果没有,您可以考虑设置全局系统环境变量。或者,您可以在执行脚本之前设置它,即在运行它的批处理文件中。

原因是我的LANG环境变量设置为en_US,而它应该被en_US.UTF-8

解决问题的另一种方法是将PYTHONENCODING设置为UTF-8(对我来说它是空的)。

我仍然不完全理解为什么 Python 只对非交互式脚本感到困惑......

更多详细信息: https://simulrpi.readthedocs.io/en/latest/display_problems.html

最新更新