看似简单的问题:我如何在Python3中print()
一个字符串?应该很简单:
print(my_string)
但这并不奏效。根据{{1}}的内容,您使用的环境变量和操作系统将引发my_string
异常:
UnicodeEncodeError
是否有一种干净的便携方式来解决这个问题?
扩展一点:这里的问题是Python3字符串包含Unicode编码字符,而终端可以有任何编码。如果你很幸运,你的终端可以处理字符串中包含的所有字符,一切都会好的,如果你的终端不能(例如有人设置>>> print("\u3423")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character '\u3423' in position 0: ordinal not in range(128)
),那么你会得到一个例外。
如果您在Python3中手动编码字符串,则可以提供忽略或替换不可编码字符的错误处理程序:
LANG=C
对于 "\u3423".encode("ascii", errors="replace")
我没有看到插入错误处理程序的简单方法,即使有错误处理程序,一个简单的错误处理程序似乎是一个糟糕的主意,因为它会修改数据。一个条件错误处理程序可能会起作用(即检查print()
并根据该做什么做出决定),但是对于isatty()
一个字符串经历所有麻烦似乎非常hacky我甚至不确定在某些情况下它不会失败。
一个现实世界的例子,这个问题就是这个问题:
答案 0 :(得分:1)
是否有一种干净的便携方式来解决这个问题?
设置PYTHONIOENCODING=<encoding>:<error_handler>
例如
$ PYTHONIOENCODING=utf-8 python your_script.py >output-in-utf-8.txt
在您的情况下,我会将您的环境(LANG
,LC_CTYPE
)配置为接受非ascii输入:
$ locale charmap
答案 1 :(得分:1)
解决此问题的最实用方法似乎是将输出编码强制为utf-8:surrogateescape
。这不仅会强制UTF-8输出,还会确保可以打印代理转义的字符串(由os.fsdecode()
返回),而不会抛出异常。在命令行上,这看起来像这样:
PYTHONIOENCODING=utf-8:surrogateescape python3 -c 'print("\udcff")'
要在程序中执行此操作,必须重新分配stdout
和stderr
,这可以通过(line_buffering=True
很重要,否则输出会赢得&#39}。得到正确的冲洗):
import sys
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, errors="surrogateescape", line_buffering=True)
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, errors="surrogateescape", line_buffering=True)
print("\udcff")
这种方法会导致字符错误地显示在未设置为UTF-8的终端上,但对我而言,这似乎更倾向于随机抛出异常,并且无法打印文件名而不会破坏文件名,因为它们可能不是在Linux系统上完全有效的编码。
我在一些地方读到utf-8:surrogateescape
可能会成为未来的默认值,但从Python 3.6.0b2开始就不是这样。
答案 2 :(得分:-1)
它给你一个错误的原因是因为它试图解读你的错误。就像\ r是ascii用于回车,\ n - 换行符\ t - 制表符等...
如果:
my_string = '\u112'
print(my_string)
这会给你一个错误,打印&#39; \&#39;没有它试图找出什么是\是这样的:
my_string = '\\u122'
print(my_string)
输出:
\u122