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 3.5.1 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"と言う名前でコピーしてパスの通った同じディレクトリに置く。
>python test.py|encfix > test.txt >type test.txt テスト テスト テスト
期待通りの結果を得られた。