第一:reload(sys)
仅根据输出终端流的需要设置一些随机默认编码是不好的做法。reload
通常会根据环境更改sys中已放置的内容,例如sys.stdin / stdout流,sys.excepthook等。
解决标准输出上的编码问题
我所知道的解决sys.stdout 上print
' 编码unicode字符串和超越ascii 的编码问题str
(例如,从文字中获取)的最佳解决方案是:照顾一个sys.stdout(类似于文件的对象),它具有以下功能:在需求方面可以选择容忍:
如果sys.stdout.encoding
是None
出于某种原因,或者根本不存在,或者错误地将其错误或“小于” stdout终端或流真正具备的能力,则尝试提供正确的.encoding
属性。最后,用sys.stdout & sys.stderr
翻译的类文件对象代替。
当终端/流仍然不能对所有出现的unichar字符进行编码时,并且当您不希望print
仅仅因为这个而中断时,可以在类似文件的翻译对象中引入“替换编码”行为。
这里是一个例子:
#!/usr/bin/env python
# encoding: utf-8
import sys
class SmartStdout:
def __init__(self, encoding=None, org_stdout=None):
if org_stdout is None:
org_stdout = getattr(sys.stdout, 'org_stdout', sys.stdout)
self.org_stdout = org_stdout
self.encoding = encoding or \
getattr(org_stdout, 'encoding', None) or 'utf-8'
def write(self, s):
self.org_stdout.write(s.encode(self.encoding, 'backslashreplace'))
def __getattr__(self, name):
return getattr(self.org_stdout, name)
if __name__ == '__main__':
if sys.stdout.isatty():
sys.stdout = sys.stderr = SmartStdout()
us = u'aouäöüфżß²'
print us
sys.stdout.flush()
在Python 2/2 + 3代码中使用超出ascii的纯字符串文字
我认为将全局默认编码(仅更改为UTF-8)的唯一好理由是有关应用程序源代码的决定-并不是因为I / O流编码问题:用于将超出ASCII字符串文字写入代码而无需强制始终使用u'string'
样式Unicode转义。可以相当一致地完成此操作(尽管使用了“”或ascii(无声明)。更改或删除仍然非常愚蠢的方式的库致命地依赖于chr#127(目前很少见)以外的ascii默认编码错误。 anonbadger通过照顾Python 2或Python 2 + 3源代码基础(可以一致地使用ascii或UTF-8纯字符串文字),的文章如此说)-只要这些字符串可能会保持沉默Unicode转换并在模块之间移动或可能转到stdout。为此,请选择“# encoding: utf-8
并在上述SmartStdout
方案之外,在应用程序启动时(和/或通过sitecustomize.py)执行此操作-无需使用reload(sys)
:
...
def set_defaultencoding_globally(encoding='utf-8'):
assert sys.getdefaultencoding() in ('ascii', 'mbcs', encoding)
import imp
_sys_org = imp.load_dynamic('_sys_org', 'sys')
_sys_org.setdefaultencoding(encoding)
if __name__ == '__main__':
sys.stdout = sys.stderr = SmartStdout()
set_defaultencoding_globally('utf-8')
s = 'aouäöüфżß²'
print s
这样,字符串文字和大多数操作(字符迭代除外)可以轻松工作,而无需考虑Unicode转换,就好像只有Python3。当然,文件I / O始终需要特别注意编码-就像Python3一样。
注意:在将原始字符串SmartStdout
转换为相应的输出流之前,会将其从utf-8隐式转换为unicode in 。