まずreload(sys)
、出力ターミナルストリームの必要性に関するランダムなデフォルトエンコーディングを設定することは悪い習慣です。reload
sys.stdin / stdoutストリーム、sys.excepthookなど、環境に応じて配置されているsysの内容を変更することがよくあります。
stdoutのエンコードの問題を解決する
sys.stdoutでprint
unicode文字列とbeyond-asciiをstr
(たとえばリテラルから)エンコードするエンコード問題を解決するために私が知っている最良の解決策は、次のことが可能です。必要に応じてオプションで許容:
ときにsys.stdout.encoding
あるNone
いくつかの理由で、または存在しない、または誤って偽または「以下」標準出力端子またはストリームが本当に可能であるものよりも、正しい提供しようとする.encoding
属性を。最後にsys.stdout & sys.stderr
、翻訳するファイルのようなオブジェクトに置き換えます。
ターミナル/ストリームがまだ発生するすべてのUnicode文字をエンコードできない場合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ストリームのエンコーディングの問題によるものではありません。常にu'string'
スタイルユニコードエスケープを使用する。これは、asciiまたはUTF-8のプレーンな文字列リテラルを一貫して使用するPython 2またはPython 2 + 3のソースコードに注意を払うことで(anonbadgerの記事の内容にかかわらず)一貫して行うことができます。ユニコード変換し、モジュール間を移動するか、潜在的にstdoutに移動します。そのためには、「# encoding: utf-8
"またはascii(宣言なし)。chr#127(今日では珍しい)を超えるasciiデフォルトのエンコーディングエラーに致命的な方法で依然依存しているライブラリを変更または削除します。
そして、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
このようにして、文字列リテラルとほとんどの操作(文字の反復を除く)は、Python3のみのようにユニコード変換を考えることなく快適に動作します。もちろん、ファイルI / Oは常にPython3と同様に、エンコーディングに関して特別な注意が必要です。
注:その後SmartStdout
、プレーンストリングは暗黙的にutf-8からUnicodeに変換されてから、出力ストリームエンコードに変換されます。