More Related Content
Similar to PyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツール (20)
More from Atsuo Ishimoto (10)
PyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツール
- 1. PyCon JP 2012
Hands on session
FlaskによるWebアプリケーションの実装と
プログラミングツール
Atsuo Ishimoto
2012/9/16 PyCon JP 2012 Hands on session 1
- 2. 講師陣 - 質問はこちらまで
@atsuoishimoto
@jbking
@feiz
近くの席の人とも話し合ってみよう!
2012/9/16 PyCon JP 2012 Hands on session 2
- 6. profileによるパフォーマンス測定
• 10分
• PythonのcProfileモジュールの使い方
• ソースコードのトレース
• ボトルネックの検出
2012/9/16 PyCon JP 2012 Hands on session 6
- 9. タイムチャート
10:00 - 10:05 アジェンダ
10:05 - 10:15 環境設定
10:15 - 10:45 Flaskアプリケーションの開発
10:45 - 11:00 休憩
11:00 - 11:10 loggingモジュール
11:10 - 11:20 traceによるパフォーマンス測定
11:20 – 11:40 デバッガの使い方
11:40 - 11:45 Q/A
• 早めに課題が終わった方は、先に進んでも結
構です
• 余裕があったら、周囲の人を助けてあげよう!
2012/9/16 PyCon JP 2012 Hands on session 9
- 10. 環境設定
• 無線Lan、つながってますね?
– www.python.org の接続を確認してください
• Python2.6 or 2.7 動きますね?
– コンソールで python の起動を確認してください
c:¥>python
Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32
bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more
information.
2012/9/16 PyCon JP 2012 Hands on session 10
- 11. パッケージ管理ツール
(Linux/OS-X/Cygwin)
• Flaskをインストールするためのパッケージ管
理ツールを用意します
• easy_install がインストール済みならそのまま
使ってください
• 無ければ
– http://python-distribute.org/distribute_setup.py
をダウンロード
– $sudo python distribute_setup.py
2012/9/16 PyCon JP 2012 Hands on session 11
- 12. パッケージ管理ツール
(Windows)
• Flaskをインストールするためのパッケージ管
理ツールを用意します
• easy_install がインストール済みならそのまま
使ってください
• 無ければ
– http://python-distribute.org/distribute_setup.py
をダウンロード
– C:¥Python27¥python.exe distribute_setup.py
2012/9/16 PyCon JP 2012 Hands on session 12
- 13. Flaskのインストール
• Windowsの場合
– C:¥Python27¥Scripts¥easy_install.exe flask
• Unix系(Linux/OS-X/Cygwin)の場合
– sudo easy_install flask
• 動作確認
– python –c "import flask" でエラーが出なければOK
2012/9/16 PyCon JP 2012 Hands on session 13
- 14. FlaskによるWebアプリケーション
1. プロジェクトディレクトリの作成
mkdir pyconjp_2012
pyconjp_2012
cd pyconjp_2012
mkdir templates handson.py
mkdir static templates
message_form.html
show_messages.html
static
style.css
2012/9/16 PyCon JP 2012 Hands on session 14
- 16. handson.py
# -*- coding: utf-8 -*-
# /add_messageでリクエストのメッセージを登録
from flask import Flask, request, session @app.route('/add_message', methods=['POST'])
from flask import render_template, redirect, url_for def add_message():
# Sessionにメッセージを登録
# Flaskのアプリケーション オブジェクトを作成 msgs = session.get('messages', [])
app = Flask(__name__) msgs.append(request.form['message'])
session['messages'] = msgs[-10:]
return redirect(url_for('show_messages'))
# http://localhost:5000/でアクセスされる関数
@app.route('/')
def index_html(): # /showでリクエストのメッセージを登録
return """ @app.route('/show')
<!doctype html> def show_messages():
<ul> # テンプレートファイル templates/show_messages.htmlを表示
<li><a href="/message_form">メッセージ追加</a></li> return render_template('show_messages.html',
<li><a href="/show">メッセージ表示</a></li>
</ul> messages=reversed(session['messages']))
"""
def main():
# /message_formでアクセスされる関数 app.secret_key = "secret"
@app.route('/message_form') app.run(debug = True)
def message_form():
# テンプレートファイル templates/message_form.htmlを表示 if __name__ == '__main__':
return render_template('message_form.html') main()
2012/9/16 PyCon JP 2012 Hands on session 16
- 17. message_form.html
<!doctype html>
<link rel=stylesheet type=text/css href="{{ url_for('static',
filename='style.css') }}">
<title>メッセージ登録</title>
<h1>メッセージ登録</h1>
<form method="post" action="{{url_for('add_message')}}">
<div>メッセージ :
<input type="text" name="message" size=40>
<button type="submit">登録</button>
</div>
</form>
2012/9/16 PyCon JP 2012 Hands on session 17
- 18. show_messages.html
<!doctype html>
<link rel=stylesheet type=text/css href="{{ url_for('static',
filename='style.css') }}">
<h1>登録済みメッセージ</h1>
{% for message in messages %}
<div>{{ message }}</div>
{% endfor %}
<hr/>
<a
href="{{ url_for('message_form') }} ">戻る</a>
2012/9/16 PyCon JP 2012 Hands on session 18
- 19. style.css
<!doctype html>
<link rel=stylesheet type=text/css href="{{ url_for('static',
filename='style.css') }}">
<title>メッセージ登録</title>
<h1>メッセージ登録</h1>
<form method="post" action="{{url_for('add_message')}}">
<div>メッセージ :
<input type="text" name="message" size=40>
<button type="submit">登録</button>
</div>
</form>
2012/9/16 PyCon JP 2012 Hands on session 19
- 21. FlaskによるWebアプリケーション
5. ソースコード解説
app = Flask(__name__) Flaskアプリケーションオブジェクトの作成
@app.route('/') @app.route('URL')で、URLへの
def index_html():
return "Hello"
リクエストハンドラを指定
render_template(
Jinja2テンプレートを実行
'テンプレートファイル',
arg=vale)
app.secret_key = "secret" セッションを利用するためのおまじない
2012/9/16 PyCon JP 2012 Hands on session 21
- 22. FlaskによるWebアプリケーション
6. jinja2テンプレート解説
<link rel=stylesheet type=text/css
href="{{ url_for('static', filename='style.css') }}">
{{ 式 }} で式をHTMLに展開
{{ url_for(…) }} でファイルへのURLを取得
{% for message in messages %}
<div>{{ message }}</div>
{% endfor %}
{% for x in xx %} ~ {% endfor %} で for ループ
2012/9/16 PyCon JP 2012 Hands on session 22
- 24. cProfileモジュール
(注) Debian/Ubuntu では、
$sudo apt-get install python-profiler
が必要な場合があります
• profile/cProfileはPythonスクリプトの実行速度
を測定するモジュールです
• 関数の呼び出し回数や処理時間を集計します
• profileとcProfileの機能はほぼ同じですが、C言
語版のcProfileの方が高速です
2012/9/16 PyCon JP 2012 Hands on session 24
- 25. cProfileモジュール
• show_messages()関数を修正します(Python2.6用)
@app.route('/show')
def show_messages():
return render_template('show_messages.html',
messages=reversed(session['messages']))
@app.route('/show')
def show_messages():
import cProfile
localvars = locals().copy()
cProfile.runctx("""ret = render_template('show_messages.html',
messages=reversed(session['messages']))""",
globals(), localvars)
return localvars["ret"]
2012/9/16 PyCon JP 2012 Hands on session 25
- 26. cProfileモジュール
• show_messages()関数を修正します(Python2.7用)
@app.route('/show')
def show_messages():
return render_template('show_messages.html',
messages=reversed(session['messages']))
@app.route('/show')
def show_messages():
import cProfile
localvars = locals().copy()
cProfile.runctx("""ret = render_template('show_messages.html',
messages=reversed(session['messages']))""",
globals(), localvars, sort='cumulative')
return localvars["ret"]
2012/9/16 PyCon JP 2012 Hands on session 26
- 27. ローカル変数を参照するコードをプロファイル
def spam():
ham = 100
value = egg(ham)
return value
def spam(): cProfile.runctx()には、
ham = 100
localvars = locals().copy() ローカル変数辞書をコピーして渡す
cProfile.runctx(
“value = egg(ham)”, locals()が返す辞書(sys._getframe().f_locals)は、
globals(), localvars) インタープリタの都合で初期化されてしまう場合があるため
return localvars[‘value’]
更新されたローカル変数は、コピー
した辞書から値を取得する
2012/9/16 PyCon JP 2012 Hands on session 27
- 28. cProfileモジュール
実行結果
4569 function calls (4272 primitive calls) in 0.005 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.005 0.005 <string>:1(<module>)
…
ncalls 呼び出し回数
tottime 他の関数呼び出しの時間を含まない、この関数での処理時間
percall 呼び出し一回あたりの関数内処理時間(tottime ÷ ncall)
cumtime 他の関数呼び出しを含む、この関数の総処理時間
percall 呼び出し一回あたりの総処理時間(cumtime ÷ ncall)
Filename:lineno ファイル名と行番号、関数名など
2012/9/16 PyCon JP 2012 Hands on session 28
- 29. loggingモジュール
• 実行ログを出力するフレームワーク
LoggerオブジェクトはHandler で
ルート logger イベントをテキスト化して出力する
Spam Logger Egg Logger
ハンドラ
Spam.Ham
Loggerオブジェクトは階層構造を
Logger 持ち、イベントを上位のLoggerに
通知する Window
ファイル
イベントログ
イベント Syslog
2012/9/16 PyCon JP 2012 Hands on session 29
- 30. Flaskのロギングサポート
• Debug用のloggerが用意されている
• message_form()を関数を修正します
@app.route('/message_form')
def message_form():
return render_template('message_form.html')
@app.route('/message_form')
def message_form():
import logging
app.logger.setLevel(logging.DEBUG) # 出力対象のイベントを指定
app.logger.debug(u"デバッグメッセージ")
app.logger.error(u“エラーメッセージ:%s;%d“, “Spam”, 100) # 文字列変換
return render_template('message_form.html')
2012/9/16 PyCon JP 2012 Hands on session 30
- 31. pdbモジュール
• Python Debugger
• 変数・コールスタックの表示、ステップ実行など
• とりあえずブレークしてみよう
@app.route('/message_form')
def message_form():
return render_template('message_form.html')
@app.route('/message_form')
def message_form():
import pdb; pdb.set_trace()
return render_template('message_form.html')
2012/9/16 PyCon JP 2012 Hands on session 31
- 32. pdbモジュール
• (Pdb)というプロンプトが表示されたらコマンド
入力可能
c:¥cygwin¥home¥ishimoto¥src¥handson¥handson.py(26)messag
e_form()
-> return render_template('message_form.html')
(Pdb)
2012/9/16 PyCon JP 2012 Hands on session 32
- 33. pdbモジュール
コマンド 意味 例
l(ist) 実行中のソース行を表示する (Pdb) l
w(here) 実行中の呼び出し履歴を表示する (Pdb) w
p式 式の値を計算して表示する (Pdb) p var1
args 関数の引数を表示する (Pdb) args
! ステートメント ステートメントを実行する (Pdb) ! var1 = 'spam'
s(tep) 次の行まで実行する。次の行が関数呼び (Pdb) s
出しなら、その関数の先頭行まで実行する
n(ext) 次の行まで実行する。次の行が関数呼び (Pdb) n
出しなら、その関数が終了して現在の関数
に復帰するまで実行する。
c(ontinue) Pdbプロンプトから抜けて、処理を続行する。 (Pdb) c
2012/9/16 PyCon JP 2012 Hands on session 33