エンコーディング指定
- odz buffer: Pythonのエンコーディング (http://d.hatena.ne.jp/odz/20080106/1199638622)
入出力周りのエンコーディングの設定の方法が書かれていた。この例で、エンコーディングを取得する前半と入出力のエンコーディングを設定する後半に分けて考える。
import sys, locale, codecs
enc = locale.getpreferredencoding()
sys.stdout = codecs.getwriter(enc)(sys.stdout)
sys.stdin = codecs.getreader(enc)(sys.stdin)
『Pythonチュートリアル』には以下のコードが載っていた。
import codecs, sys sys.stdout = codecs.lookup('utf-8')[-1](sys.stdout)
後半部分は、以下のように同じことをやっているだけ。
>>> import codecs >>> codecs.lookup('utf-8') <codecs.CodecInfo object for encoding utf-8 at 0x1437d88> >>> list(codecs.lookup('utf-8')) [<built-in function utf_8_encode>, <function decode at 0x014E37F0>, <class encodings.utf_8.StreamReader at 0x0143BED0>, <class encodings.utf_8.StreamWriter at 0x0143BEA0>] >>> >>> codecs.getwriter('utf-8') <class encodings.utf_8.StreamWriter at 0x0143BEA0>
前半のlocale.getpreferredencoding()は、ユーザが使用していると推測されるcharsetを取得している。これをそのまま指定した場合に問題が発生するケースが書かれた以下の記事を見つけた。
- METAREAL: Python: Mac OS X での locale.getpreferredencoding()
- METAREAL: Apple によるロケール周りの変更点を Python 2.5.1 にも適用する
Tracでは、前半部分を以下のようにしているみたい。但し、単なる安全対策っぽいのであまり本質的ではないかも。
...(略)... encoding = locale.getpreferredencoding() or sys.getdefaultencoding() if sys.platform != 'win32': encoding = locale.getlocale(locale.LC_TIME)[1] or encoding # the above is broken on win32, e.g. we'd get '437' instead of 'cp437' ...(略)...
但し、気になったのは、MAC OS XでPython 2.5.1をソースからインストールした場合に発生した以下のような問題点。
記事に書かれていたのは回避方法として、locale.pyにパッチを当てるという方法だった。パッチによりgetpreferredencoding()関数定義の分岐を変更したりしている。
まとめると、odz bufferさんの方法は、確かにベストプラクティスかもしれない。但し、getpreferredencoding()関数の内容によってはPythonで使用できないencodingが返ってしまいLookupErrorが発生する可能性はあるということは意識しておく必要はあると思う。
以下の2つのどちらかの対策は必要かもしれない。
- encをアプリごとにユーザが自分で'utf-8'や'cp932'などと直接指定する
- LookupErrorが出た場合はユーザにlocale.pyにパッチを当ててもらう
YAMLとJSON
Wikipediaからの引用。
JSON(ジェイソン、JavaScript Object Notation)は、JavaScriptにおけるオブジェクトの表記法をベースとした軽量なデータ記述言語である。
Pythonの標準ライブラリでYAMLとJSONを扱うものを探してみたが標準にはないっぽい。JSONは、JavaScriptでファイル内の文字列をeval()すればそのままオブジェクトに変換される。同じ発想でPythonで、params.pyを用意して、import paramsすれば良いというやり方でも良いのではないか?名づけてPySON (パイソン、Python Script Object Notation)。
というか仕事でこのやり方をしているのだが、注意点としては日本語の扱いやpy2exeでexe化する際に一緒にparams.pyを含めないように気を付けるだけであり、全く問題ない。一番手っ取り早いし、パラメータ用のファイルを取り込んでいるだけなので、それほど黒魔術的な訳でもない。というかJSONでもほとんど同じ。PySONでは、importする前に動的にsys.pathにパスを追加もできるのでパス設定も問題ない。
Pythonの標準ライブラリに存在しないということは必要性が低いと言えるのかもしれない。