PySQLite2.4.1+でマルチバイトを扱う時の注意点
うちのMacで、MailArchiveExtPluginでTracに日本語メールを取り込むと、以下のエラーが発生するようになってしまった。
ProgrammingError: You must not use 8-bit bytestrings unless you use
a text_factory that can interpret 8-bit bytestrings (like text_factory = str).
It is highly recommended that you instead just sitch your application
to Unicode strings.
以前は動いてた気がするので、Snow Leopardに入れ替えた影響かなぁと思いつつ調べてみた。
上記エラーメッセージでググるとそこそこひっかかります。
- http://d.hatena.ne.jp/veryberry_cafe/20061012/1160667054
- http://ytaro-wps.blogspot.com/2009/01/python-django-djmall-python-2.html
- http://d.hatena.ne.jp/kamataro/20081012/1223829973
エラーメッセージにも書いてあるが、Unicode文字列(Unicode strings)を使ってないのが原因らしい。確かに、MailArchiveExtPluginのエラー発生箇所は以下で、Unicode文字列をUTF-8でエンコードしてstr型(バイト列型)に変換し、PySQLiteに渡しているんだよね。
cursor.execute("UPDATE mailarc SET " "category=%s, utcdate=%s, zoneoffset=%s, subject=%s," "fromname=%s, fromaddr=%s, header=%s, text=%s, threadroot=%s, threadparent=%s " "WHERE messageid=%s", (self.category.encode('utf-8'), self.utcdate, self.zoneoffset, self.subject.encode('utf-8'), self.fromname.encode('utf-8'), self.fromaddr.encode('utf-8'), '', self.body.encode('utf-8'), self.thread_root, self.thread_parent, self.messageid))
さらに調べると、djangoのサイトにばっちし書いてある!
if Database.version_info >= (2,4,1): # Starting in 2.4.1, the str type is not accepted anymore, therefore, # we convert all str objects to Unicode # As registering a adapter for a primitive type causes a small # slow-down, this adapter is only registered for sqlite3 versions # needing it. Database.register_adapter(str, lambda s:s.decode('utf-8'))
なるほどね、、まとめると
- PySQL 2.4.1以降では、str型だとマルチバイトは弾くようになった
- なので、Unicode文字列で送ってやる必要がある
- 確かに、うちのMacはPySQL 2.4.1でした(>_