如何在Python3中打印()一个字符串,没有例外?

时间:2014-03-19 02:03:16

标签: python-3.x python-unicode

看似简单的问题:我如何在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我甚至不确定在某些情况下它不会失败。

一个现实世界的例子,这个问题就是这个问题:

Python3: UnicodeEncodeError only when run from crontab

3 个答案:

答案 0 :(得分:1)

  

是否有一种干净的便携方式来解决这个问题?

设置PYTHONIOENCODING=<encoding>:<error_handler>例如

$ PYTHONIOENCODING=utf-8 python your_script.py >output-in-utf-8.txt

在您的情况下,我会将您的环境(LANGLC_CTYPE)配置为接受非ascii输入:

$ locale charmap

答案 1 :(得分:1)

解决此问题的最实用方法似乎是将输出编码强制为utf-8:surrogateescape。这不仅会强制UTF-8输出,还会确保可以打印代理转义的字符串(由os.fsdecode()返回),而不会抛出异常。在命令行上,这看起来像这样:

PYTHONIOENCODING=utf-8:surrogateescape python3 -c 'print("\udcff")'

要在程序中执行此操作,必须重新分配stdoutstderr,这可以通过(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