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

Python 以utf-8格式将unicode字符打印到终端,python,python-3.x,utf-8,Python,Python 3.x,Utf 8,我使用Python 3.9.1和Linux(CentOS 7)。我想在控制台上打印unicode字符。我想用UTF-8做所有的事情。如果我打开python交互控制台并编写: 打印(“├") 一切顺利,它打印出: ├ 现在我把同一行print(“├“”,然后使用UTF-8编码保存文件(linux上的默认设置)。 然后我得到以下错误: UnicodeEncodeError: 'latin-1' codec can't encode character '\u251c' in position 0:

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

打印(“├")

一切顺利,它打印出:

现在我把同一行
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中的默认值)

但这并没有改变任何事情

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

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编码的源文件中)将字符
\u251C
分配到
s
的第一个位置,即UTF-8编码的字符串

print(s)
失败,因为这里的print将表示
s
的字节发送到标准输出,标准输出需要
latin-1
编码。实际上,类似
s.encode('latin-1')
的操作失败,因为字符串中的第一个字符无法正确编码

如果您实际运行该语句(
s.encode('latin-1')
),您会发现它会导致相同的错误

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

打印(s2)
确实可以打印
b'\xe2\x94\x9c'
,因为它只是打印字节序列的Python表示。它不是字符串,所以可以打印值的表示。应该是,它是可以用来定义
s2
的文本,即
s2=b'\xe2\x94\x9c'
不会改变任何东西

print(s2.decode('latin-1'))
打印正确的东西有点神秘。
s2
是U+251C字符的正确UTF-8字节序列()

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

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

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

如本文所述,您可以通过设置
SET PYTHONENCODING=UTF-8
来实现这一点。相反,如果您想在交互环境中复制问题,您可能可以通过
pythonlegacycynowsstdio
获得该行为


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

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

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

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


更多详细信息:

我假设您使用的是Windows?当您运行脚本时,它似乎正在打印到使用
latin-1
编码的环境中?即,脚本运行的控制台窗口没有使用UTF-8编码?我不太明白,
print(s2.decode('latin-1'))
永远不要打印正确的内容,因为s2是utf-8编码的。请检查环境变量的值。
LANG
环境变量设置为什么?他们非常清楚这是Linux环境,所以我认为
PYTHONLEGACYWINDOWSSTDIO
不会有任何区别。请尝试
import sys;print(sys.stdin.encoding,sys.stdout.encoding)
使用原始的
LANG
设置,在交互提示和脚本中查看Python在每个场景中使用的默认编码。您还可以设置
PYTHONUTF8=1
以启用UTF-8模式。
s = "├"
#print(s) # FAIL
s2 = s.encode('utf8')
print(s2) # prints b'\xe2\x94\x9c'
print(s2.decode('latin-1')) # prints the right thing