web-dev-qa-db-ja.com

Python)のsys.stdoutを介してUnicode文字列を書き込む

しばらくの間、printを使用できないと仮定します(したがって、自動エンコーディング検出の利点を享受できます)。つまり、sys.stdoutが残ります。ただし、sys.stdoutは非常に馬鹿げているので 意味のあるエンコーディングは行いません

ここで、Python wikiページ PrintFails を読み、次のコードを試してみます。

$ python -c 'import sys, codecs, locale; print str(sys.stdout.encoding); \
  sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout);

ただし、これも機能しません(少なくともMacでは)。理由がわかりすぎます:

>>> import locale
>>> locale.getpreferredencoding()
'mac-roman'
>>> sys.stdout.encoding
'UTF-8'

(UTF-8は端末が理解できるものです)。

したがって、上記のコードを次のように変更します。

$ python -c 'import sys, codecs, locale; print str(sys.stdout.encoding); \
  sys.stdout = codecs.getwriter(sys.stdout.encoding)(sys.stdout);

これで、Unicode文字列がsys.stdoutに適切に送信されるため、端末に適切に出力されます(sys.stdoutは端末に接続されています)。

これはsys.stdoutでUnicode文字列を書く正しい方法ですか、それとも何か他のことをする必要がありますか?

[〜#〜] edit [〜#〜]:時々-たとえば、出力をless--sys.stdout.encodingにパイプするときNoneになります。この場合、上記のコードは失敗します。

17

印刷ができない理由は私にはわかりません。しかし、そうだとすれば、そうです、アプローチは私には正しく見えます。

3
export PYTHONIOENCODING=utf-8

仕事をしますが、それをpython自体に設定することはできません...

私たちにできることは、が設定されていないかどうかを確認し、スクリプトを呼び出す前に設定するようにユーザーに指示することです。

if __name__ == '__main__':
    if (sys.stdout.encoding is None):
        print >> sys.stderr, "please set python env PYTHONIOENCODING=UTF-8, example: export PYTHONIOENCODING=UTF-8, when write to stdout."
        exit(1)
31
Sérgio

最良のアイデアは、端末に直接接続されているかどうかを確認することです。もしそうなら、端末のエンコーディングを使用してください。それ以外の場合は、システム優先エンコーディングを使用してください。

if sys.stdout.isatty():
    default_encoding = sys.stdout.encoding
else:
    default_encoding = locale.getpreferredencoding()

また、ユーザーが必要なエンコーディングを常に指定できるようにすることも非常に重要です。通常、私はそれをコマンドラインオプション(-e ENCODINGなど)にし、optparseモジュールで解析します。

もう1つの良い点は、notsys.stdoutを自動エンコーダーで上書きすることです。エンコーダーを作成して使用しますが、sys.stdoutはそのままにしておきます。エンコードされたバイト文字列をsys.stdoutに直接書き込むサードパーティライブラリをインポートできます。

10
nosklo

オプションの環境変数「PYTHONIOENCODING」があり、これを希望のデフォルトエンコーディングに設定できます。これは、すべてのPythonと一貫性のある方法で、ユーザーが希望するエンコーディングを取得する1つの方法です。 Pythonマニュアル ここ に埋もれています。

8
daveagp

これは私が私のアプリケーションで行っていることです:

sys.stdout.write(s.encode('utf-8'))

これは、argvからUTF-8名を読み取るための正反対の修正です。

for file in sys.argv[1:]:
    file = file.decode('utf-8')

これは非常に醜い(IMHO)ので、UTF-8を使用する必要があります。これはLinux/Macでは標準ですが、Windowsでは標準ではありません...とにかく私には機能します:)

7
elcuco