2009年04月10日

python defaultencodingがevilな感じ

>>> print '%s,%s' % (u'日本語', u'abc')
日本語,abc
>>> print '%s,%s' % ('日本語', 'abc')
日本語,abc
>>> print '%s,%s' % (u'日本語', 'abc')
日本語,abc
>>> print '%s,%s' % ('日本語', u'abc')
Traceback (most recent call last):
File "", line 1, in
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 0: ordinal not in range(128)

というようなエラーが出る。
どうやらユニコードマーク付き文字列と、無印文字列を並べた場合、python自体の内部エンコードがasciiなのにunicode文字列を出力しようとしたためデコードできないということのようだ。
特にタプル等を使用した場合に要素すべての文字コードがasciiかunicodeになっていない場合に遭遇しやすい。

>>> import sys
>>> sys.getdefaultencoding()
'ascii'

上記でpythonの内部エンコードは確認できる。通常はasciiになっていることがほとんどだ。
これをutf-8に変更しようとして下記のように実行すると

>>> sys.setdefaultencoding('utf-8')
File "", line 1, in
AttributeError: 'module' object has no attribute 'setdefaultencoding'

とそんなアトリビュートは無いと返される。
その場合は一度モジュールをreloadすると成功する。

>>> reload(sys)

>>> sys.setdefaultencoding('utf-8')
>>> sys.getdefaultencoding()
'utf-8'

>>> print '%s,%s' % (u'日本語', u'abc')
日本語,abc
>>> print '%s,%s' % ('日本語', 'abc')
日本語,abc
>>> print '%s,%s' % (u'日本語', 'abc')
日本語,abc
>>> print '%s,%s' % ('日本語', u'abc')
日本語,abc

なぜこの関数に関してreloadが必要なのか調べてはいないが、なにやら非常にすっきりしないものを感じる。
自分の管理範囲のOSであれば{$libdir}/python2.6/site-packages/sitecustomize.pyに下記のように書いておけばよい。

import sys
sys.setdefaultencoding('utf-8')

ただし仕事でおさめるスクリプト等では実行環境のデフォルトエンコーディングがどう指定されているか保証されないため、スクリプトの初期に上記のようなチェックと設定をすればよい。
その前にすべての変数の文字コードをあわせなさいよ、という話なのかもしれないが。。。

確認した環境
macos 10.5 python2.5
macports python2.4, 2.5, 2.6
centos 5(64bit) python2.4

kaz0215 at 07:37コメント(2)トラックバック(0) 

トラックバックURL

コメント一覧

1. Posted by setdefaultencoding   2009年04月11日 01:13
この関数は、siteモジ ュールの実装が、sitecustomizeモジュールから使用するためだけに 定義されています。siteから呼び出された後、この関数は sysから削除されます。
http://www.python.jp/doc/nightly/lib/module-sys.html
2. Posted by ほんにん   2009年09月04日 02:41
コメントくれた方、本当にありがとうございます。
うっかり5ヶ月近く気づきませんでした。
ごめんなさい。。

コメントする

名前:
URL:
  情報を記憶: 評価:  顔   星
 
 
 
楽天市場
livedoor × FLO:Q
QRコード
QRコード
  • ライブドアブログ