文字コードの†闇†遭遇レポート part1


状況

Windows7 64bit,Python2.7.5にて
以前から使っていたFoursquareのVenueを集めるクローラをツール化した.
自分しか使わないので,入出力とかは割と適当に.
入力はbboxの右上と左下それぞれの緯度経度,出力はID,Venue名,緯度経度,ジャンル,
を,csvに書き出すことを想定してカンマ区切りで.
コマンドライン上で実行することを想定したので,出力はリダイレクトでファイルに書き込めるように標準出力.
入力待ちのときに,なにを入力するのか,テキストをエラー出力(「北東端の緯度」とか表示).
ソースコードはutf-8で記述.

†闇†の症状

コマンドライン上で以下のように実行.

command1
$ python foursquare_crawler.py > washington_venues.csv
蛹玲擲遶ッ縺ョ邱ッ蠎ヲ・

文字化けした…
この部分のソースコードは以下の通り.

source1
sys.stderr.write("北東端の緯度:")
first_ne_lat = float(sys.stdin.readline())

単純にコマンドプロンプトの文字コードが悪いと思い,一時的にコマンドプロンプトの文字コードをcp932(Shift-JIS)からutf-8に変更.
Windowsではutf-8のことをcp65001というらしい…

command2
$ chcp 65001
Active code page: 65001

もう一度実行.

command3
$ python foursquare_crawler.py > washington_venues.csv
北東端の緯度:

…(´・ω・`)
今度はプログラム内でエラー出力をutf-8で出力するように明示的に記述.

source2
sys.stderr = codecs.getwriter('utf-8')(sys.stderr)
sys.stdin = codecs.getwriter('utf-8')(sys.stdin)
sys.stderr.write("北東端の緯度:")
first_ne_lat = float(sys.stdin.readline())

ついでに標準入力もutf-8で受け取るように書いた.
しかし変わらず…

解決方法

どうしたもんかねーと思い,なんとなくUnicodeにした.

source3
sys.stderr.write(u"北東端の緯度:")
first_ne_lat = float(sys.stdin.readline())

ついでにコマンドプロンプトの文字コードも一旦元に戻して実行.

command3
$ chcp 932
現在のコード ページ: 932
$ python foursquare_crawler.py > washington_venues.csv
北東端の緯度:

できたー(゚∀゚)!!!
詳しく調べてないけど,普通は文字列はバイトごとに管理するから,文字列を複数バイトに分割するときに,日本語とかの全角文字とアルファベットとかの半角文字でいろいろ問題があるらしい.
でもUnicodeだと,1文字は1文字で処理するから,Pythonで日本語を扱うときはUnicodeがいいらしい.

今度から文字列は全部Unicodeにしよう…