[英]Print unicode characters to terminal in utf-8
我使用 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)
“latin-1”从何而来?
我也在第一行强制使用 UTF-8(这应该是 Python3 中的默认值)
# coding: utf8
但它不会改变任何东西。
关于什么有效,什么无效的更多信息:
s = "├"
#print(s) # FAIL
s2 = s.encode('utf8')
print(s2) # prints b'\xe2\x94\x9c'
print(s2.decode('latin-1')) # prints the right thing
这里发生了什么? 我可以在脚本中获得与交互式控制台中相同的行为吗?
s = "├"
(在您的 UTF-8 编码源文件中)将字符\├
分配给s
的第一个位置, s
是一个 UTF-8 编码字符串。
print(s)
失败,因为这里的 print 将表示s
的字节发送到标准输出,该输出需要latin-1
编码。 实际上,像s.encode('latin-1')
失败,因为字符串中的第一个字符无法正确编码。
如果您从字面上运行该语句( s.encode('latin-1')
),您会发现它会导致相同的错误。
s2 = s.encode('utf8')
工作得很好,它告诉 Python 将s
的内容显式编码为字节序列。 s2
现在持有的字节的编码s
,使用UTF-8编码。 (也许 'b' 会是一个更好的变量名,毕竟它不是一个字符串)
print(s2)
确实打印b'\\xe2\\x94\\x9c'
,因为它只是打印字节序列的 Python 表示。 它不是字符串,因此您可以打印出值的表示形式。 应该是,它是您可以用来定义s2
的文字,即s2 = b'\\xe2\\x94\\x9c'
不会改变任何东西。
print(s2.decode('latin-1'))
打印正确的东西有点神秘。 s2
是 U+251C 字符的正确 UTF-8 字节序列 ( https://www.fileformat.info/info/unicode/char/251c/index.htm )
显然,您的 Python 获取s2.decode('latin-1')
的结果, 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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.