例えば標準出力にユニコード文字列を書き込むという単純極まりない処理をやってみる。
Python 2.7 を使うとこんなかんじ。
$ python --version Python 2.7.10 $ python >>> import sys >>> sys.stdout.write(u'うにこーど\n') うにこーど
何の問題もない。
Python 3.5 ならこう。
$ python --version Python 3.5.1 $ python >>> import sys >>> sys.stdout.write(u'うにこーど\n') うにこーど 6
write() メソッドが書き込んだ文字数を返すようになってる。
さて、肝心の Python 2.6 を使うとこうなる。
$ python --version Python 2.6.9 >>> import sys >>> sys.stdout.write(u'うにこーど\n') Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-4: ordinal not in range(128)
何か例外出ましたけど。
原因を調べたら古式ゆかしい Python のバグらしい。 Python 2.6 のサポートは既に終わっているので、この不具合が直ることはない。
一応、解決策がないわけではなくて次のようにすると回避できる。
>>> import sys >>> import imp >>> imp.reload(sys) <module 'sys' (built-in)> >>> import locale >>> sys.setdefaultencoding(locale.getpreferredencoding()) >>> sys.stdout.write(u'うにこーど\n') うにこーど
あるいはファイルライクオブジェクトをラップするやり方もありかな。
>>> import locale >>> class StdWrapper(object): ... def __init__(self, stream): ... self.stream = stream ... def __getattr__(self, name): ... return getattr(self.stream, name) ... def write(self, text): ... # unicode は 2.x だけにあるシンボルなので注意 ... if isinstance(text, unicode): ... text = text.encode(locale.getpreferredencoding()) ... return self.stream.write(text) ... >>> import sys >>> wrapper = StdWrapper(sys.stdout) >>> sys.stdout = wrapper >>> sys.stdout.write(u'うにこーど\n') うにこーど
ただ、どちらも LANG=C な環境なんかだと上手くいかないみたいだ。
結論
古いバージョンを使い続けることはリスク。
スマートPythonプログラミング: Pythonのより良い書き方を学ぶ
- 作者: もみじあめ
- 発売日: 2016/03/12
- メディア: Kindle版
- この商品を含むブログを見る