偏った言語信者の垂れ流し

2011-07-06

[][]コマンドプロンプトでのPython文字コードについて

Pythonでコマンドツールを作ってて、パイプでつなげたりするときに色々はまったのでメモ。

WindowsXPでPython2.7。

# coding: utf-8


def main():
    print u"テスト"  # PYTHONIOENCODINGでエンコードされる
    print "テスト"  # このファイルの文字コード(utf-8)
    print u"テスト".encode('cp932')  # cp932にエンコードされる

if __name__ == '__main__':
    main()

これをコマンドプロンプトから実行するとこうなる。

>python test.py
テスト
繝・せ繝
テスト

この出力を、文字化けがない状態でファイルに書き出したい。

ちなみに、出力をリダイレクトしようとするとエラーになる。

>python test.py > test.txt
Traceback (most recent call last):
  File "test.py", line 10, in <module>
    main()
  File "test.py", line 5, in main
    print u"繝・せ繝・  # PYTHONIOENCODING縺ァ繧ィ繝ウ繧ウ繝シ繝峨&繧後k
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)

PYTHONIOENCODINGにcp932を設定すると通る

1. Command line and environment — Python v2.7.4 documentation

>set PYTHONIOENCODING=cp932
>python test.py > test.txt
>type test.txt
テスト
繝・せ繝・
テスト

さてここで、2行目のUTF-8の化けてるものを読める状態にしたい。

chardet モジュールを使ってこんなスクリプトを書いた。

encfix-script.py

#!C:/Python27/python.exe
import sys
import chardet


def main():
    s = sys.stdin.read()
    for line in s.splitlines():
        result = chardet.detect(line)
        sys.stdout.write(line.decode(result['encoding']).encode('cp932') + '\n')

if __name__ == '__main__':
    main()

あとは、setuptoolsのexe(easy_install.exeとか)を"encfix.exe"と言う名前でコピーしてパスの通った同じディレクトリに置く。

f:id:nullpobug:20110706154148p:image

>python test.py|encfix > test.txt
>type test.txt
テスト
テスト
テスト

期待通りの結果を得られた。

2011/11/21追記

標準エラー出力を変換したい場合は、リダイレクトすれば良い。

>python test.py 2>&1|encfix

しみずかわしみずかわ 2011/07/06 22:48 出力するtest.py側は手出しできないコードという位置づけで、あくまで出力された後にpipeで調整したいということですね。PYTHONIOENCODINGは知りませんでした。2.6からなんですね。

nullpobugnullpobug 2011/07/06 22:53 そんな感じです、先生。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/nullpobug/20110706/1309934555