このブログサイトに登録してあるキーワードを出力するスクリプトをgdataライブラリを使って、pythonで書いているのですが、出力結果をファイルにキャッシュしておこうとしてラップしているbashスクリプトに../list_labels.py | tee labels.txt を追加したところ、次のようなエラーが発生しました。
File ".../python/list_labels.py", line 133, in run self.list_labels() File ".../python/list_labels.py", line 125, in list_labels UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-7: ordinal not in range(128)
問題になったのは次のようなコードの中で、print label
をしているところです。
...
l = []
for label in set(labels):
l.append(label)
pass
for label in sorted(l):
print label
pass
pass
Googleでとりあえず検索してみた結果
いくつかの方法がありましたが、sys.setdefaultencodingにencodingを記述するといった方法がありました。
import sysをしてからdir(sys)でみると、少なくとも手元のpython 2.7.3にはそんなメソッドは定義されていません。
次にヒットしたのはunicodeに文字列を変換するものですが、どちらかというとスクリプト中に埋め込んだutf-8文字列を画面に出力するための方法を解説しているもので、リダイレクトの時に問題が発生している事については触れられていませんでした。
pythonのバージョンに依るのかもしれませんが、この他の方法もいまいち決定的なものはありませんでした。
unicodeに変換するのではなく、リダイレクトの時の正しいencodeを指定する
解決策は次のようにencode()関数を追加して'utf-8'に変換しました。
l = []
for label in set(labels):
l.append(label)
pass
for label in sorted(l):
print label.encode('utf-8')
pass
pass
リダイレクトの時にLANGなどをみて標準的なlocaleに変化してくれれば良いのですが、リダイレクトの時にencodeが設定されないというのは、かなり悩ましい挙動です。
暗黙の挙動だから不定になるのは当然という意見もありそうですが、リダイレクトの時に挙動が切り替わるのは、やっぱり謎仕様です。rawデータとして何の処理もせずにbyte列を掃き出すなら、まだ分かるんですけどね。
ともかく無事に終わったので部屋の整理をして今日は休もうと思います。
0 件のコメント:
コメントを投稿