1. ホーム
  2. python

[解決済み] Pythonでstdoutをパイピングするときに正しいエンコードを設定する

2022-03-15 22:54:28

質問

Pythonプログラムの出力をパイピングする際、Pythonインタープリタはエンコーディングについて混乱し、それをNoneに設定します。これは、次のようなプログラムを意味します。

# -*- coding: utf-8 -*-
print u"åäö"

は、普通に実行すると正常に動作しますが、次のように実行すると失敗します。

UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 0: ordinal not in range(128)

パイプシーケンスで使用した場合。

パイピング時にこれを動作させるには、どのような方法があるのでしょうか?シェル/ファイルシステム/その他が使っているどんなエンコーディングでも使うように指示すればいいのでしょうか?

私がこれまでに見た提案は、site.pyを直接修正するか、このハックを使ってdefaultencodingをハードコーディングすることです。

# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
print u"åäö"

パイピングをうまくする良い方法はないでしょうか?

どのように解決するのですか?

Pythonはターミナルアプリケーションが使っているどんなエンコーディングにも出力をエンコードするので、あなたのコードはスクリプトで実行されたときに動作します。Pythonはターミナルアプリケーションが使っているどんなエンコーディングにも出力をエンコードするからです。

経験則から言うと 内部では常にユニコードを使用する。受信するものはデコードし、送信するものはエンコードしてください。

# -*- coding: utf-8 -*-
print u"åäö".encode('utf-8')

もう一つの教訓的な例として、ISO-8859-1とUTF-8の間を変換するPythonのプログラムがあります。

import sys
for line in sys.stdin:
    # Decode what you receive:
    line = line.decode('iso8859-1')

    # Work with Unicode internally:
    line = line.upper()

    # Encode what you send:
    line = line.encode('utf-8')
    sys.stdout.write(line)

システムのデフォルトエンコーディングを設定するのは悪い考えです。なぜなら、あなたが使っているモジュールやライブラリの中には、それがASCIIであるという事実に依存しているものがあるからです。このようなことはしないでください。