(第71回)Python mini Hack-a-thonで行った内容の個人的な備忘録です。
書いていたらついつい長くなってしまったので、何回かに分けます。
このイベント、Hack-a-thonと書いていますが、各々が好きなことをやるイベントです。 今回は、先日Qiitaで見つけた、Falconという速いらしいWebフレームワークのソースコードをPythonの勉強がてら眺めてみました。
Falconとは
情報はこちらにまとまっています。
ざっと見たところ下記のような特徴があるようです。
- ミニマルで速いWSGIアプリケーション
- ベンチマークはこちら
- HTTP and the REST architectural styleな設計
- Resourceクラスを定義して
on_get
やon_post
を実装する
- Resourceクラスを定義して
- APIサーバー向けに絞った機能だけを提供(テンプレート機能や認証などはなし)
- テストコードとドキュメントがしっかりある(コメントも豊富)
ついでにソースコード(*.py
)のファイル数や行数なども調べてみました。
ちょっとしたPythonの勉強にはちょうどいいサイズ感ではないでしょうか。
[alpaca]~/github/falcon/falcon % pwd
/Users/rhoboro/github/falcon/falcon
# ソースコードは55ファイル
[alpaca]~/github/falcon/falcon % find . -name "*.py" | wc
55 55 1181
# トータルで9500行程度。一番大きなファイルでも1351行。
[alpaca]~/github/falcon/falcon % find . -name "*.py" | xargs wc | sort -r | head
9439 39313 343961 total
1351 7370 60395 ./errors.py
1321 5517 50907 ./request.py
718 3271 27566 ./response.py
683 2913 28151 ./api.py
652 2664 24076 ./testing/client.py
457 2120 16512 ./util/uri.py
363 1394 13628 ./routing/compiled.py
334 837 9109 ./bench/bench.py
318 1144 9566 ./util/misc.py
ソースコードを読んでいく
ざっくりと概要がわかったところで、下記の流れでソースコードを読んでみました。
- QuickstartとTutorialを読んでざっくりと使い方を知る
- エントリポイントがどこかを調べる
- そこからどういう処理が行われているかを調べる
- せっかくなので、速い理由になってそうなところを調べる
エントリポイント
Falconを利用したアプリケーションの最小構成は、ドキュメントにあるとおり。
import falcon
api = application = falcon.API()
こちらのfalcon.API()
がWSGIアプリケーションになります。
でもほぼろは「WSGIアプリケーションとは」をそもそもちゃんと理解していなかったので、WSGIについても調べました。
Python Web Server Gateway Interface (WSGI)
声に出すときは「うぃすぎー」「うぃずぎー」あたりであれば恥ずかしくないです。
WSGIの詳細はPEP333をご覧ください。(どうしても日本語でという方はWikipediaを)
とても簡単にいうと、WebサーバーとWebアプリケーションを繋ぐ部分(インターフェース)の仕様です。
お互いがWSGIに準拠していれば、Webサーバを変えずにWebアプリケーション側のフレームワークを変えたりできるという利点があります。
WSGI準拠のWebサーバーとしては、gunicornやuWSGIが有名でしょうか。
Webアプリケーション側だとDjangoやFlask、Pyramid、Bottleなど有名どころはほぼ対応しています。
で、WSGIアプリケーションがやらないといけないことはざっくりとこんな感じです。
- Webサーバーにリクエストが来ると、WebアプリケーションのCallableなオブジェクトが呼び出される(falcon.API())
- このとき、Callableなオブジェクトにはパラメータとして、いろいろな環境変数とstart_responseが渡される
- Webアプリケーションは、(必要な処理を行った後)パラメータで渡された
start_response
を呼び出し、ステータスコードとヘッダーを渡す - その後、iterableなオブジェクトを返り値として返す
Webサーバーはこれらの情報からレスポンスを生成し、クライアントに返すという流れになっています。
falcon.API()
Falconでエントリポイントとなっているfalcon.API()のソースコードはfalcon/api.pyです。
class API(object):
~省略~
def __call__(self, env, start_response): # noqa: C901
~省略~
# Return the response per the WSGI spec
start_response(resp.status, headers)
return body
__call__
メソッドは、オブジェクトを関数のように呼び出し可能なオブジェクトにしてくれる特殊メソッドです。
WSGIサーバーにAPIクラスのインスタンスを渡し、リクエストがきた際にenv, start_responseをパラメータとしてこのインスタンスを呼び出してもらいます。
そして、ごにょごにょと処理を行った後、start_response(resp.status, headers)
でステータスコードとヘッダーを渡し、body(これはiterableなオブジェクト)を返しています。
すべてのリクエストでこの処理が毎回行われることになります。
ちゃんと上述したWSGIアプリケーションに沿った動きになっていますね!
次回に続く
WSGIの説明しかしてない気もしますが、今回はここまで(笑)
次回はもう少しソースコードを読んでいて気になったところをピックアップするつもりです。
HTTPはステートレスなものなので、いまの状態などを意識しないでいいのは普段モバイル開発をしている身としては楽ですね!
スマホアプリはそれ自体がステートフルなものなので、常に状態を気にせずにはいられない...orz