2010年12月22日水曜日

Werkzeugのデバッガ

鹿に尻をかじられたりもしましたが、
三日間の奈良旅行で、8万歩以上も歩き、とても充実した休暇をすごしました。

Python Web フレームワーク アドベントカレンダー2010 のバトンがまわってきたので、Werkzeugの紹介をします。
http://werkzeug.pocoo.org/

Werkzeugはみなさんご存知のFlaskの作者であるArminが作ったWEBフレームワークです。
実はFlaskのベースでもあります。
単体で使っても便利ですが、非常によい機能が詰め込まれているため、各種フレームワークに組み込んで使う人が多いようです。
たとえば、django-extensionsでDjangoに組み込んで使う人も多いでしょう。
私も、どんなWEBアプリケーションでもほとんどの場合、開発時に組み込んでいます。
運用時にも使うケースは少なくありません。

丁寧なチュートリアルもついているのですが、なにぶん、生のWSGIが露出しているフレームワークなので、
分かりやすいとは言えません。
今回は、便利な機能の一部に焦点を合わせて解説します。

さて、解説前に少し準備しましょう。
まず、ごく小さなアプリを一つ書きます。
hello.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from werkzeug import Response, script

def app(environ, start_response):
    response = Response('Hello, World!')
    return response(environ, start_response)

action_runserver = script.make_runserver(lambda: app)
action_shell = script.make_shell(lambda: {})

if __name__ == '__main__':
    script.run()

pythonでライブラリを試すときはVirtualenvが便利です。
wget https://bitbucket.org/ianb/virtualenv/raw/eb94c9ebe0ba/virtualenv.py
python virtualenv.py ~/.virtualenvs/pyadvc
source ~/.virtualenvs/pyadvc/bin/activate
pip install werkzeug
python hello.py runserver

http://localhost:5000/にアクセスするとHello, World!と表示されるはずです。

デバッガ

JavaやC#ではステップ実行を使ってデバッグするケースがあると思います。
Pythonでもpdbを使ってステップ実行ができますが、ブレークポイントを設定するのが面倒ですね。
WerkzeugではアプリケーションがExceptionをWerkzeugに投げたのを捕まえて、WEB画面上でステップ実行をすることができます。
ためしに一つエラーを起こしてみましょう

def app(environ, start_response):
    a = 'Hello'
    response = Response('%a, World!'%a)
    return response(environ, start_response)
app関数を書き換えてもう一度起動してみましょう
するとおなじみのInternal Server Errorが出るはずです。
これではエラーの原因がわかりません。
ただ、コンソールでは
response = Response('%a, World!'%a)
 ValueError: unsupported format character 'a' (0x61) at index 1
というように表示されているので、エラーの推測はできるでしょう。
ここで、%aが正しくないことはわかったのですが、なにが正しいのでしょうか。
そこでデバッガです。

python hello.py runserver --debugger
という引数をつけて起動しましょう。
再度表示してみると、カラフルな画面が表示されるようになりました。

Traceback (most recent call last)

  • File "/home/spam/ws/python/wz/hello.py", line 7, in app

    response = Response('%a, World!'%a)

response = Response('%a, World!'%a)

と書かれた行をクリックしてみましょう。
これでソースが確認できます。

さらに、その行の右にコンソールっぽいアイコンがありますのでクリックします。
すると[console ready]と表示されました。
これはPythonのコンソールです。
たとえば 1 + 1とすると2と返答があるはずです。
さて、直したいのは
'%a, World!'%a
の部分です。
まず、dump()とすると、変数一覧が表示されます。

>>> dump()

Local variables in frame

a'Hello'
start_response
environ{'wsgi.multiprocess'False'SERVER_SOFTWARE''Werkzeug/0.6.2''SCRIPT_NAME''''REQUEST_METHOD''GET'  }

aに'Hello'が入っているのがわかりますね。

ここで、 '%a, World!'%a と入力すると先ほどと同じエラーが出ます。
a,b,cといろいろ試したり、マニュアルを確認したところ、%sが正しいとわかりました。
>>> '%s, World!'%a 'Hello, World!'


これで、正しい文がわかったので、ソースを書き換えて終了です。


その他、Context LocalsというJavaでいうThreadLocalを便利にした機能から、WEBアプリに必須なルーティング機能まで、すばらしい品揃えです。
そのWerkzeugの機能を丁寧にラップして、高速+多機能テンプレートエンジンであるJinja2と組み合わせたのがFlaskです。

ぜひ試してみてください。

次は@lirisさんお願いします。

0 件のコメント: