Pythonの文字化け対策:sys.setdefaultencodingの謎

PHP, 文字コード, UTF-8, Python, フレームワーク, Pylons, Django

08:05:42, by admin Email , 243 words, 7457 views   Japanese (JP) del.icio.us

これはどういうことだろう。

(ノ・・)ン。。。。。。(((●コロコロッ

$ python
Python 2.4.3 (#2, Nov 7 2006, 13:07:47)
[GCC 3.4.4 [FreeBSD] 20050518] on freebsd6
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> hasattr( sys, 'setdefaultencoding' )
False
>>> reload( sys )
<module 'sys' (built-in)>
>>> hasattr( sys, 'setdefaultencoding' )
True


( ̄-  ̄ ) ウーン

Pythonを使い始めて早幾日。
そこそこ数あるフレームワークからあれこれ使ってみる。
Spyceが想像したものと全然違って愕然とする。
メジャーなdjango, TurboGears, Zopeを選ばずPylonsを選択し、
さくらインターネットにインストールして超ハマリ。
XREA.COMにインストールすることでなんとか片づけたりと、
相変わらずあほなことをしている。
軌跡はこの辺りに。
XREA.COMでPylonsをとりあえず使ってみる


未だ言語自体を全く覚えていない。
そろそろ、書籍を一冊手元に置こう。
使いこなすにはあと数年は必要かな。。。



さて、今回問題にしたいのは文字コード。
PythonはUTF-8で書くのはデフォルトの決め事なのではあるが、
Pylons標準のMakoテンプレートエンジンを使った時に、
日本語が文字化けしてしまう問題が発生した。

まぁ、今後Pythonを使う上で避けては通れないものだし、
キチンと調べて自身の指標を立てておくことにするか。

結論はそれなりに出たのだが、
世間一般では全く使われていない方法。
相変わらずなにをやっているのやら。。。

[More:]


テンプレート上で日本語を使おうとした時のこと。
Script Errors
と表示されて、
にっちもさっちもいかない。
入力文字コードを指定すれば良いだけだと思うのだが、
Makoのマニュアルを読んでもそう言ったところは見あたらない。
テンプレートと言いつつもどうやらplain pythonという扱いのようで、
ユニコード文字列を使用する時はユニコードリテラルを付けなければならないっぽい。

(´・ω・) ソンナノテンプレジャネェ

Plain Pythonってことは先頭行に文字コード指定をしておけば、
一応回避出来る。
# coding: UTF-8
<html></head>
<body>
あいうえお
</body></html>


HTMLジャナイナ (・ω・`)

ページが一枚ならまだしも、
全部に記述するなどあり得ない。
なにか文字コードを設定する方法はないか。。。



調べてみると。
こんなサイトに出くわした。
Python開発環境を整えよう
sitecustomize.pyを設定する

まっさらなPython環境ができたので、つぎのこの環境全体の設定を行います。
~/lib/python2.4/site-packagesにsitecustomize.pyというファイルを作成しておくと、
Pyhonインタプリタ起動時に自動的に読み込まれ、
Python全体の設定を行うことができます。

よくある設定には、デフォルト・エンコーディングの設定があります。
import sys
sys.setdefaultencoding('utf-8')

デフォルト・エンコーディングは好みと必要性に応じて設定してください。
ごく一般的に使われているであろう手法。
site-packages以下にsitecustomize.pyを作成し、
デフォルトエンコーディングを設定しておく。

しかし、PHPerな私にはこの方法は悪夢を呼ぶことになりそうでとても使いたくない。
PHPでいうならphp.iniにmultibyte設定を書くようなもので、
奥底に眠らせるのはハマリの元だ。
サーバを遷した時にいきなり動かなくなったりするおそれがある。


( ̄-  ̄ ) ウーン

ではsys.setdefaultencodingを手動で実行すればいいのでは?
と思い、やってみる。
$ python
Python 2.4.3 (#2, Nov 7 2006, 13:07:47)
[GCC 3.4.4 [FreeBSD] 20050518] on freebsd6
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.setdefaultencoding('UTF-8')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: 'module' object has no attribute 'setdefaultencoding'


アリ?(・ω・)

なんで無いの?
もう少し調べてみると、

UnicodeEncodeErrorが発生した場合は、sitecustomize.pyでデフォルトのエンコーディングを指定する。
なお、sitecustomize.py以外でsys.setdefaultencodingを実行しても、AttributeErrorになります。
・・・略
これは、pythonは起動が終了したら、sysモジュールからsetdefaultencoding関数を削除するためです。
ここで、pythonの起動時の処理を、少し詳しく説明します。
pythonは起動時に、モジュールの検索パスを設定し、siteモジュールを読み込みます。
Ubuntuなら、/usr/lib/python2.4/site.pyになります。
sitecustomizeモジュールも、このsite.pyから読み込まれています。


なるほろ。
わざわざ削除しているというのは、
セキュリティ上大きな問題になるということなのだろうか。
となるとプログラムの開始時に削除されている状態にしておかねばならないな。

実行時にdefaultencodingを変更する
実行時に変更したい場合の一番楽な方法は、sysモジュールをreloadすることです。
・・・略
しかしながら、実行時にdefaultencodingを変更するのは禁じ手中の禁じ手です。
Pythonのユニコードの扱いを理解していれば、
通常は全く困ることがありませんし、
困ることがあるのはPythonのユニコードの扱いを理解していない人間が書いたライブラリやフレームワーク、
もしくは、出入力のエンコーディングに、
asciiやutf-8等の特定のエンコーディングを想定しているライブラリ・フレームワークを使いたい場合くらいのものです。
文字コードを変更するのはそんな根幹を揺るがすものなのか?
ソースコードの先頭付近に# coding: UTF-8とか打たなきゃならないのに、
エンコーディングの変更をやってはいけないというのはイマイチしっくりこない。

デフォルトエンコーディングがUTF-8と確定している場合ならまだしも、
asciiがデフォルトであることがほとんどだとすると変えざるを得ないのでは?

例えば配布用アプリケーションを作ったとして、
利用者にsitecutomize.pyを追加してくださいと案内をしなきゃならないってのはちょっと難しい。
それに内部にある設定ファイルで文字コード設定するのはハマリの元だというのは前述の通り。
言語が変わったからといってそこが変わることはない。
しかも、sitecutomize.pyはPythonが起動してから”自動で”読み込まれるだけで、
スクリプト上にあることに代わりはない。
[禁じ手中の禁じ手]という彼の意見は的はずれだ。



reloadのオーバーヘッドはどの程度のものなんだろうか。
無視出来るレベルならreloadが一番の楽な解決策だが、
あまりやりたくない方法ではあるな。
起動時のパラメータを操作する方向の方が良いか。
ちなみにPython2.5に付属していたサンプルtest_xmlrpc.pyではreload(sys)とやっていた。
中の人とて本末転倒なことをしている。

それと、twistedやpasteみたいに、
アプリケーションサーバ的に利用する場合、
パラメータ付で起動することが出来ないこともある。
sitecutomize.pyを設置することも選択肢に入れておくとしよう。


(・υ・)ッテコトハ


総合するとどうだろ。
二通り考えられるかな。
CGI実行する時は、
  • Python起動時に-Sを必ず付ける
  • sys.setdefaultencodingで文字コードを確定させる
  • 実行後,site.pyを呼び出す
#!/usr/bin/python -S
# coding: UTF-8
import sys
sys.setdefaultencoding('UTF-8')
import site


デーモン起動する時は、
  • sitecustomize.pyを設置
import sys
sys.setdefaultencoding('UTF-8')


という感じかな。


挙動も安定したし、
いちいちリテラルに振り回されることもなくなった。
Unicode文字列使ってもシステムが止まることもなくなったし、
しばらくこんな感じで様子を見るとするか。


Trackback address for this post:

http://hain.jp/htsrv/trackback.php/188

Comments, Trackbacks:

Comment from: methane [Visitor] · http://dsas.blog.klab.org/
mod_cidr試していただいてありがとうございます。

Makoですが、optionにinput_encodingがあるようです。
Pylonsの場合でしたら、
http://wiki.pylonshq.com/display/pylonsdocs/Unicode#templating
ここで、output_encoding を指定しているのと同じ方法で、input_encoding を指定できると思います。
PermalinkPermalink 2008/10/03 @ 16:39

Leave a comment:

Your email address will not be displayed on this site.
Your URL will be displayed.

Allowed XHTML tags: <p, ul, ol, li, dl, dt, dd, address, blockquote, ins, del, span, bdo, br, em, strong, dfn, code, samp, kdb, var, cite, abbr, acronym, q, sub, sup, tt, i, b, big, small>
(Line breaks become <br />)
(Set cookies for name, email and url)
(Allow users to contact you through a message form (your email will NOT be displayed.))
This is a captcha-picture. It is used to prevent mass-access by robots.

Please enter the characters from the image above. (case insensitive)

powered by b2evolution

shinobi

Neighbors
Relative
Favorites
PR

極論istの技術屋を始めて早幾年。 流れの速い業界の波にもまれながらも精一杯生きている様をとくとごらんあれ。

Archives
スポンサー

Latest bookmark
Search

Categories

Who's Online?
Misc
Syndicate this blog XML

Valid XHTML 1.0! Valid CSS! Valid RSS 2.0! Valid Atom 1.0!