我正在尝试寻找一种通用的解决方案来从python脚本中打印unicode字符串。
要求是它必须在Python2.7和3.x中运行,在任何平台上,并且使用任何终端设置和环境变量(例如LANG=C或LANG=en_US.UTF-8)。
python打印函数在打印时会自动尝试对终端编码进行编码,但如果终端编码是ascii,则会失败。
例如,当环境为“LANG=enUS.UTF-8”时,可以执行以下操作:
x = u'\xea'
print(x)但在Python2.7中,当“LANG=C”时失败:
UnicodeEncodeError: 'ascii' codec can't encode character u'\xea' in position 0: ordinal not in range(128)无论LANG设置如何,以下命令都有效,但如果终端使用不同的unicode编码,则无法正确显示unicode字符:
print(x.encode('utf-8'))期望的行为是,如果可能,总是在终端中显示unicode,如果终端不支持unicode,则显示一些编码。例如,如果终端仅支持ascii,则输出将采用UTF-8编码。基本上,目标是在python print函数工作时执行与python print函数相同的操作,但在print函数失败的情况下,使用一些默认编码。
发布于 2014-12-08 05:13:31
您可以通过告诉sys.stdout在其他情况下默认为LANG=C时使用UTF-8来处理ASCII码。
import sys, codecs
if sys.stdout.encoding is None or sys.stdout.encoding == 'ANSI_X3.4-1968':
utf8_writer = codecs.getwriter('UTF-8')
if sys.version_info.major < 3:
sys.stdout = utf8_writer(sys.stdout, errors='replace')
else:
sys.stdout = utf8_writer(sys.stdout.buffer, errors='replace')
print(u'\N{snowman}')上面的代码片段满足了您的需求:它可以在Python2.7和3.4中工作,并且当LANG处于非UTF-8设置(比如C )时,它不会中断。
它是not a new technique,但在文档中很难找到它。如上所述,它实际上遵循非UTF-8设置,比如ISO 8859-*。只有当Python错误地默认为ASCII时,它才会默认为UTF-8,从而中断应用程序。
发布于 2014-12-08 05:14:46
我不认为您应该尝试在Python级别上解决这个问题。记录您的应用程序需求,记录您运行的系统的区域设置,以便可以将其包含在错误报告中,并将其留在那里。
如果确实想这样做,至少要区分终端和管道;永远不要将数据输出到终端无法显式处理的终端;例如,不要输出UTF-8,因为在编码时,不可打印的codepoints > U+007F最终可能被解释为控制代码。
对于管道,默认输出UTF-8并使其可配置。
因此,您将检测是否正在使用TTY,然后基于此处理编码;对于终端,设置一个错误处理程序(选择replace或backslashreplace之一,为无法处理的任何字符提供替换字符或转义序列)。对于管道,请使用可配置的编解码器。
import codecs
import os
import sys
if os.isatty(sys.stdout.fileno()):
output_encoding = sys.stdout.encoding
errors = 'replace'
else:
output_encoding = 'utf-8' # allow override from settings
errors = None # perhaps parse from settings, not needed for UTF8
sys.stdout = codecs.getwriter(output_encoding)(sys.stdout, errors=errors)发布于 2014-12-09 05:25:46
您可以自己使用特殊参数'backslashreplace'对字符串进行编码,以便将无法表示的字符转换为转义序列。在Python2中,您可以直接打印encode的结果,但是在Python3中,您需要首先将其decode回Unicode。
import sys
encoding = sys.stdout.encoding
print(s.encode(encoding, 'backslashreplace').decode(encoding))如果sys.stdout.encoding不能提供您的终端所能处理的价值,那就是您必须处理的另一个问题。
https://stackoverflow.com/questions/27347772
复制相似问题