2017年12月21日

Python 3.7 でテキストファイルのエンコーディングを初期化後に変更可能になります

はてなブックマークに登録

Python のテキストファイル (厳密には io.TextIOWrapper) はいままでコンストラクタでしかエンコーディングを指定することができませんでした。

特に標準入出力 (sys.stdin, sys.stdout, sys.stderr) のエンコーディングを設定するには環境変数 PYTHONIOENCODING を利用するしかなく、アプリケーションが設定ファイルなどに基づいてこれらのエンコーディングを変更するには sys.stdin を sys.stdin.fileno() や sys.stdin.buffer から作り直すなどのハック的な方法しか使えませんでした。

Python 3.7 からは TextIOWrapper に reconfigure() メソッド メソッドが追加され、一部のコンストラクタで設定するオプションを変更可能になります。 そして昨日このメソッドに encoding, errors, newline のサポートを追加しました。 (コミット)

これにより sys.stdin.reconfigure(encoding='EUC-JP') のようにしてエンコーディングを変更することができます。

Python 3.7 は PEP 538 と 540 によって UTF-8 を使う限りにおいてはほぼ不満ない状態になったと思いますが、これで UTF-8 以外が必要な場合についても「one obvious way」を提供できるようになったと思います。

注意点として、read側については、少しでも read していると変更できず、エラーになります。これは TextIOWrapper 内部で、下側(bufferd IO)からある程度のかたまりでバイト列を受け取り、それをバッファに置いてデコードして改行で区切って返しているので、とくに状態をもつエンコーディングのデコーダを使っている場合に「返したところまで」と「それ以降」のバイト単位での区切りをつけるのが難しいからです。

書き込み側については、単に flush() してから新しいエンコーディングのエンコーダを作り直せばいいので、途中からのエンコーディングの変更にも対応しています。


@methane

songofacandy at 17:40│Comments(0)Python 

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 
Blog内検索
Archives
このブログについて
DSASとは、KLab が構築し運用しているコンテンツサービス用のLinuxベースのインフラです。現在5ヶ所のデータセンタにて構築し、運用していますが、我々はDSASをより使いやすく、より安全に、そしてより省力で運用できることを目指して、日々改良に勤しんでいます。
このブログでは、そんな DSAS で使っている技術の紹介や、実験してみた結果の報告、トラブルに巻き込まれた時の経験談など、広く深く、色々な話題を織りまぜて紹介していきたいと思います。
最新コメント