続・玩式草子 ―戯れせんとや生まれけん―

第7回 ウィスキー・ボトル・ブルース(1番)

この記事を読むのに必要な時間:およそ 4 分

突然ですが,皆さんは"Bottle"というPython用のWebフレームワークを知っていますか?

"Webフレームワーク"というと,大規模なWebサービスを構築するためのツールで,自分には関係ない,と思われる方も多いかも知れません。しかしながら,趣味でWebサイトを作っている場合でも,写真類は日付やキーワードを元に動的に呼び出したり,家計簿管理用にバックエンドでデータベースを使いたくなることはよくあるでしょう。

Bottleはそのような際に便利なWebフレームワークで,Pythonのモジュールとして書かれた1つのファイルをimportするだけで,PythonスクリプトがWebアプリになる便利なツールです。

筆者自身,まだ半年くらいしか使っていない初心者なものの,2,3のWebアプリを書いてみてその便利さに感心したので,同じような興味を持っている人向けに,今回からしばらく,この"Bottle"というWebフレームワークを紹介してみようと思います。

Bottleの実行例

"Bottle"はpip等を使ってインストールすることもできるものの,bottle.pyという1つのファイルだけで構成されているので,使いたいディレクトリに配置するだけで使えます。

たとえば,"Bottle-test"というディレクトリでテスト用のコードを書く場合,そのディレクトリにbottle.pyというファイルをダウンロードするだけでインストールは完了です。

$ mkdir Bottle-test ; cd Bottle-test
$ wget https://bottlepy.org/bottle.py
$ ls -l
合計 172,032
-rw-r--r-- 1 kojima users 170,346  2月 22日  21:00 bottle.py

次にこのディレクトリに次のようなPythonスクリプトを用意します。ファイル名は"hello.py"としておきましょう。

 1     #!/usr/bin/python
 2     # -*- coding: utf-8 -*-
 3     
 4     from bottle import route, run
 5     
 6     @route("/")
 7     def hello():
 8         return("Hello World")
 9     
10     run(host='localhost', port=8080, reloader=True, debug=True)

このスクリプトを起動すると,importされたbottleの機能で,8080番のポートを見張るWebサーバとして動作します。

$ python hello.py
Bottle v0.13-dev server starting up (using WSGIRefServer())...
Listening on http://localhost:8080/
Hit Ctrl-C to quit.

この状態でfirefox等のブラウザから "http://localhost:8080/" を開くと,"Hello World"というメッセージが表示されます。

図1 Hello Worldの例

図1 Hello Worldの例

この画面だけではショボく見えるかも知れませんが,httpdサーバを立ちあげなくても,HTMLなページを書かなくても,bottle.pyをimportするだけでWebサービスを提供できるというのは凄いことだと思いませんか?

HTMLで簡単なWebアプリを作ろうとすると,入力用のページ⁠,出力用のページ⁠,編集用のページ等々,必要な機能ごとのHTMLファイルを用意して,どのようにデータを受け渡すかを考慮しつつ,各ページをリンクでつないでやる必要がありました。

一方,Bottleを使えば,それらの機能は全てPythonの関数として書けるので,1つのスクリプトだけでWebアプリを完結することができます。

筆者自身,⁠Webフレームワーク」というとRailsやStrutsを連想し,⁠大規模なWebアプリを作るためのもので,高機能ではあるけれど設定や準備が大変そう⁠⁠,という先入観を持っていたので,Bottleのこの単純さには目から鱗が落ちる思いでした。

ルーティング機能

新しいURLを追加するために,前節のhello.pyに3行ほど書き加えてみます。追加したのは10から13行目です。

 1     #!/usr/bin/python
 2     # -*- coding: utf-8 -*-
 3     
 4     from bottle import route, run
 5     
 6     @route("/")
 7     def hello():
 8         return("Hello World")
 9
10     @route("/hello/<name>")
11     def greet(name):
12         return("Hello {}".format(name))
13
14     run(host='localhost', port=8080, reloader=True, debug=True)

ちなみに14行目のrunコマンドがBottleを起動する命令で,引数に"reloader=True"を指定しておけば,スクリプトを修正すると自動的に再読み込みしてくれるので便利です。また,"debug=True"はデバッグメッセージを出力するための指定です。

この状態で "http://localhost:8080/hello/kojima" を開くと,"Hello kojima"というメッセージが出力されます。

図2 URLに引数を取る例

図2 URLに引数を取る例

これらの例が示すように,Bottleでは@route(...)という指定でURLとPythonの関数を結びつけ,"http://localhost:8080/"では7行目の"def hello():"が,"http://localhost:8080/hello/kojima" では11行目の"def greet(name):" が実行されます。

このようにURLと関数を結びつける指定をルーティング(routing)と呼んでいます。ルーティングには完全なURLを指定することも,10行目の"/hello/<name>"のように可変部分を含めることもできます。この"<...>"で囲んだ部分には"/hello/kojima"や"/hello/Tanaka"のような任意の文字列が対応し,ここに指定した文字列(name)が11行目の"def greet(name)"の引数としてPythonスクリプトに取り込まれます。

@route()の"@"はPythonの"デコレータ"という機能で,その名の通り直下の関数を修飾するために使われます。上記の例では,7行目のhello()と11行目のgreet(name)関数を修飾し,return()された結果を8080のポート経由で接続しているクライアント宛に送るように変更して,Webサーバの機能を果しているわけです。

著者プロフィール

こじまみつひろ

Plamo Linuxとりまとめ役。もともとは人類学的にハッカー文化を研究しようとしていたものの,いつの間にかミイラ取りがミイラになってOSSの世界にどっぷりと漬かってしまいました。最近は田舎に隠棲して半農半自営な生活をしながらソフトウェアと戯れています。

URLhttp://www.linet.gr.jp/~kojima/Plamo/index.html