web-dev-qa-db-ja.com

Python 3:stdinエンコーディングの指定方法

Python 2からPython 3へのコードの移植中に、標準入力からUTF-8テキストを読み取ると、この問題が発生します。InPython 2、これは正常に動作します:

for line in sys.stdin:
    ...

しかし、Python 3はASCII fromsys.stdinを期待します。入力に非ASCII文字が含まれていると、エラーが発生します。

UnicodeDecodeError: 'ascii'コーデックはバイトをデコードできません..の位置に..:範囲外の序数(128)

通常のファイルの場合、ファイルを開くときにエンコードを指定します。

with open('filename', 'r', encoding='utf-8') as file:
    for line in file:
        ...

しかし、標準入力のエンコーディングをどのように指定できますか?その他SO投稿(例 Pythonでstdinエンコーディングを変更する方法 )は、

input_stream = codecs.getreader('utf-8')(sys.stdin)
for line in input_stream:
    ...

ただし、これはPython 3.では機能しません。それでも同じエラーメッセージが表示されます。Ubuntu12.04.2を使用していて、ロケールがen_US.UTF-8に設定されています。

34
Seppo Enarvi

Python 3はしないASCII from _sys.stdin_を期待します。これはstdinを開きますテキストモードで、どのエンコーディングが使用されているかについて知識に基づいた推測を行います。その推測はASCIIに帰着する可能性がありますが、それは与えられていません。 _sys.stdin_のドキュメント を参照してくださいコーデックの選択方法について。

テキストモードで開かれた他のファイルオブジェクトと同様に、_sys.stdin_オブジェクトは _io.TextIOBase_基本クラス から派生します。それは、基になるバッファ付きのIOインスタンスを指す_.buffer_属性を持ちます(インスタンスには_.raw_属性があります)。

_sys.stdin.buffer_属性を新しい io.TextIOWrapper() instance でラップして、別のエンコーディングを指定します。

_import io
import sys

input_stream = io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8')
_

または、Pythonの実行時に PYTHONIOENCODING環境変数 を目的のコーデックに設定します。

Python 3.7以降、 既存の_std*_ラッパーを再構成する を開始することもできます(データが読み込まれる前に)。

_# Python 3.7 and newer
sys.stdin.reconfigure(encoding='utf-8')
_
67
Martijn Pieters