2014
03
30
03
30
Python: 最近のWebフレームワーク
PythonでWebアプリを公開したいとなると、手順がかなり手っ取り早く済むGoogleAppEngine。当初はオリジナルのフレームワークのみで開発だったが、最近はFlask、Django、bottleで開発ができるようになっており選択の幅が広まっている。しかしデータストアはGoogleの提供する独自のものしか使えない。これはこれで結構使えるんだけど、mongoDBに興味が出てきたので使ってみたくて、そのためにはGAEを脱する必要がある。そんなわけでGoogleAppEngineから入門したけど他の環境でのWebアプリ構築も可能になりたいという考えでPythonの代表的なフレームワークをあさってみる。なるべく規模が小さいものがいいのでDjango以外で。
比較のために"Hello, world"プラスαのコードを各フレームワークで書いてみる。ただ"Hello World"を表示するものならそれぞれのフレームワークの紹介ページに出ている。とくに使われるであろうHTTPリクエストにはGETやPOSTなど数種類のメソッドがあり、それをどう使い分けるのかも知りたい。フォームに名前を入力してポストし、サーバはJSONで入力された名前を返すページも用意する。

GAEで使われているwebapp2は外でも使えるように公開されている。なかなかコンパクトで使いやすいけど、3.xに対応する前に開発がストップしてしまっている。今後のことを考えると3への対応は欲しいのでwebapp2は切ることにする。ただwebappの書き方に慣れているので、こういうクラスベースで書くwebpyと似たようなフレームワークだとありがたい。
FacebookでオープンソースにされているTornadoというものがある。webpyやwebapp2に酷似していてとっつきやすいが、ノンブロッキングというめずらしい特徴がとくにデータストアを使う上で独自性を出すことになる。まあそのあたりは別の機会に。
続いてFlask。これは現行でかなり人気が高いらしく、高機能ならDjangoで軽さならFlaskだと聞いたような気がする。関数ベースで書くようなのでちょっと不慣れ。だけどその辺は慣れればいいだけのはなしだ。Python 3.xもサポートに入っているし。
最後にBottle。とりあえずFlaskとあまり変わらないコードになった。こっちも開発が継続中で、Python 3.xにも対応している。
Pyramidというのも人気を博してきているが、中規模以上に向いていてちょっと小さくないという印象。
webpyやwebapp2がPython 3.xに対応していればよかったんだけど、先々のことを考えて他の選択肢を探ろうといくつかWebフレームワークにあたってみた。どれもそれらにそっくりそのままというわけにはいかないけど、それなり共通部分があって難しくなさそう。こういう場合は開発頻度やコミュニティで選べばいいのかな。
比較のために"Hello, world"プラスαのコードを各フレームワークで書いてみる。ただ"Hello World"を表示するものならそれぞれのフレームワークの紹介ページに出ている。とくに使われるであろうHTTPリクエストにはGETやPOSTなど数種類のメソッドがあり、それをどう使い分けるのかも知りたい。フォームに名前を入力してポストし、サーバはJSONで入力された名前を返すページも用意する。

import webapp2
import json
class MainHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('Hello, World!')
class GreetingHandler(webapp2.RequestHandler):
def get(self):
html = """<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>
function send()
{
$.post("/g", {name:$("#name_form").val()}, function(data)
{
$("#greeting").prepend("Welcome, " + data["name"] + "<br>");
}, "json");
}
</script>
</head>
<body>
your name:<input id="name_form"/>
<button onclick="send();">greeting</button>
<div id="greeting"></div>
</body>
</html>
"""
self.response.write(html)
def post(self):
name = self.request.get("name")
j = {"name":name}
self.response.headers['Content-Type'] = "application/json"
self.response.write(json.dumps(j))
application = webapp2.WSGIApplication([
('/', MainHandler),
('/g', GreetingHandler),
], debug=True)
GAEで使われているwebapp2は外でも使えるように公開されている。なかなかコンパクトで使いやすいけど、3.xに対応する前に開発がストップしてしまっている。今後のことを考えると3への対応は欲しいのでwebapp2は切ることにする。ただwebappの書き方に慣れているので、こういうクラスベースで書くwebpyと似たようなフレームワークだとありがたい。
FacebookでオープンソースにされているTornadoというものがある。webpyやwebapp2に酷似していてとっつきやすいが、ノンブロッキングというめずらしい特徴がとくにデータストアを使う上で独自性を出すことになる。まあそのあたりは別の機会に。
import tornado.ioloop
import tornado.web
import json
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
class GreetingHandler(tornado.web.RequestHandler):
def get(self):
html = """<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>
function send()
{
$.post("/g", {name:$("#name_form").val()}, function(data)
{
$("#greeting").prepend("Welcome, " + data["name"] + "<br>");
}, "json");
}
</script>
</head>
<body>
your name:<input id="name_form"/>
<button onclick="send();">greeting</button>
<div id="greeting"></div>
</body>
</html>
"""
self.write(html)
def post(self):
name = self.get_argument("name")
j = {"name":name}
self.write(json.dumps(j))
if __name__ == "__main__":
application = tornado.web.Application([(r"/", MainHandler),
(r"/g", GreetingHandler),
], debug=True)
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
続いてFlask。これは現行でかなり人気が高いらしく、高機能ならDjangoで軽さならFlaskだと聞いたような気がする。関数ベースで書くようなのでちょっと不慣れ。だけどその辺は慣れればいいだけのはなしだ。Python 3.xもサポートに入っているし。
from flask import Flask
from flask import request
app = Flask(__name__)
import json
@app.route("/")
def hello():
return "Hello World!"
@app.route('/g', methods=["GET", "POST"])
def greet():
if request.method == "GET":
html = """<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>
function send()
{
$.post("/g", {name:$("#name_form").val()}, function(data)
{
$("#greeting").prepend("Welcome, " + data["name"] + "<br>");
}, "json");
}
</script>
</head>
<body>
your name:<input id="name_form"/>
<button onclick="send();">greeting</button>
<div id="greeting"></div>
</body>
</html>
"""
return html
elif request.method == "POST":
name = request.form["name"]
j = {"name":name}
return json.dumps(j)
if __name__ == '__main__':
app.run(debug=True)
最後にBottle。とりあえずFlaskとあまり変わらないコードになった。こっちも開発が継続中で、Python 3.xにも対応している。
from bottle import route, run, request
import json
@route("/")
def hello():
return "Hello World!"
@route('/g', method=["GET", "POST"])
def greet():
if request.method == "GET":
html = """<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>
function send()
{
$.post("/g", {name:$("#name_form").val()}, function(data)
{
$("#greeting").prepend("Welcome, " + data["name"] + "<br>");
}, "json");
}
</script>
</head>
<body>
your name:<input id="name_form"/>
<button onclick="send();">greeting</button>
<div id="greeting"></div>
</body>
</html>
"""
return html
elif request.method == "POST":
name = request.forms.get("name")
j = {"name":name}
return json.dumps(j)
run(host='localhost', port=8888)
Pyramidというのも人気を博してきているが、中規模以上に向いていてちょっと小さくないという印象。
webpyやwebapp2がPython 3.xに対応していればよかったんだけど、先々のことを考えて他の選択肢を探ろうといくつかWebフレームワークにあたってみた。どれもそれらにそっくりそのままというわけにはいかないけど、それなり共通部分があって難しくなさそう。こういう場合は開発頻度やコミュニティで選べばいいのかな。
スポンサーサイト