Re: google app engine のユニコードの処理に苦しんだ方への処方箋
hikaliの開発日誌 | [Pythonゲーム修行]google app engine のユニコードの処理に苦しんだ方への処方箋
とりあえず
Python 2.5.2 (r252:60911, Nov 29 2008, 16:55:50) [GCC 4.0.1 (Apple Inc. build 5465)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> print "あ" + "い" あい
というわけで
Pythonの内部では、マルチバイト文字列はUnicodeでないと処理できない。
これも、知らないと結構はまるのですが(当然できるものと思い込んでいるため)、たとえば「+」を使って文字列を連結することもできません。
というのは事実誤認。
それから
>>> print u"あ" + "a" # (1) あa >>> print u"あ" + None # (2) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: coercing to Unicode: need string or buffer, NoneType found >>> print u"あ" + 1 # (3) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: coercing to Unicode: need string or buffer, int found
(1)のように、ユニコード文字列にそうでない文字列を結合する際には、ユニコード文字列でない側をユニコード文字列に変換する。そこで例えば文字列やバッファーでないものが来た場合は「ユニコードに変換しようとしたけど文字列じゃないよこれ」ってエラーが出る。(2)では「文字列ではなくNoneTypeが来た」、(3)では「文字列ではなく整数が来た」とエラーメッセージに書いてある。
せっかく対話的シェルで簡単に試すことが出来るんだから、よくわからないことが起きたら小さい単位に砕いて挙動を確認してみると理解が進むのにな、と思った。
追記: id:voluntas と「早くPython3000への移行が進めばいいのにねー」とか話していたんだけど、そうかせっかくだからその件についてもここに書いといた方がいいのか。上の(1)のコードは「デフォルトのエンコーディングを使ってバイト列をユニコード文字列に変換してから結合」という挙動をするわけだけど、けっこう多くの人がデフォルトエンコーディングがなんであるかとか、コードでfoo + barと書いたときにこの+で変換が怒るのかどうかとかに無自覚なのでバグの温床になる。そこでPython3000からは(1)もTypeErrorになるように変更になった。明示的に変換してから結合する習慣を付けること。