フルスタックなオールインワンのWebフレームワークDjango

寺田学氏(以下、寺田):「Webフレームワークの紹介」に移ります。Django、Flask、Pyramid、Zope、Tornado、aiohttp、Guillotina、Bottle、responderの9種類の紹介をしていきます。

まず、Djangoの説明です。Djangoの公式サイトはここ(https://www.djangoproject.com/)です。Django Software Foundationという組織がマネジメントして作っています。BSDライセンスです。

最初のリリースは1.0.1で、2008年や7年ぐらいから使われていたんですが、1.0という意味での最初のリリースは2010年です。最近のリリースは資料を先に作ってから1年間いろいろやっているので、1月1日現在のバージョンが、このあとの資料にもたいてい書いてあります。

今は2.1.4です。すでに2.4があったり、3.0の声が聞こえたりもしていますが。一言でいうと、フルスタックなオールインワンのWebフレームワークだと思っています。フルスタックで、オールインワンでいろんなものが入っているWebフレームワークです。

次に、私にとっていいところと、微妙だなと思うところです。いいところは、Django adminというデータベースの管理画面です。これはやっぱり便利です。データベースを管理するときに、わざわざSQLを叩かなくても画面を簡単に提供してくれる。

ただ、微妙な点としては、私にとっては少しオリジナリティが強いです。Djangoは、pipでいろんなものをインストールするというより、Djangoの中で閉じているという特徴があります。そういう意味で、他のPython Webフレームワークに乗り換えようとするときに、ハードルができてしまう可能性がある。

Django流のところがある代わりに、マイグレーションがしやすいとか、Djangoの中で閉じているという良さもあります。

さっきお話しした機能の一覧で、(Djangoには)どれが入っていて、どれが入っていないか。永続化のレイヤー、データベースのレイヤーはORMです。データベースの接続の部分だけはあります。データベースは入っていません。当たり前のことを言うなということかもしれませんが、SQL系のデータベースはだいたい持ってくるのが標準的な使い方です。

さっきも説明しましたが、WSGIに対応しているので、runコマンドなどはDjangoの提供ではないわけです。テストサーバはもちろんありますが、GunicornとかuWSGIとかと一緒に組み合わせて使うものです。REST APIは、アドオンで有名なDRF(Django REST framework)というフレームワークがあります。

データとかローカルデータの扱いとしては、リクエストオブジェクトの中に入れてやる。リクエストオブジェクトはブラウザから送信されたものなので、その中にポンポンと入れていくんですけど、そこはリクエストオブジェクトに入れないといけないという感じはあるかもしれません。

Asyncサーバにはなっていませんが、3.0に向けて、そういう声も聞こえています。ただ、すべてをAsyncにするのは、データベースの接続までAsyncにしないといけないので、すごく大変なんです。なので、Asyncサーバにはなるけど、中身がすべて簡単にポンとAsyncで作れるかというと、その先の未来がまだ見えていないと聞いています。セットアップはpipでやって、Pythonコードで環境変数などを作るというかたちです。

シンプルで便利なWebフレームワークFlask

次はFlask。Flaskもけっこう有名ですよね。Armin Ronacherという、2012年に日本のPyConにも来てもらった、すごいエンジニアが作ったものです。彼の個人プロジェクトだった時期もかなり長いです。彼はもう手を引き気味で、グループでいろいろやろうとしているんですけど、DjangoのようにFoundationを持っているわけではないので、どう作られていくのかが見えにくい部分はあります。

BSDライセンスです。0.1は2010年で、最新は1.0.2ですね。一言でいうと、シンプルで便利なWebフレームワークです。

いいところとしては、小さなコンポーネントなので簡単に作りやすい感じがします。それから、人気があるフレームワークなので、検索すれば多くの事例が見つかる。Djangoの次点がFlaskかなと思います。

ただ、微妙な点としては、自由すぎるんです。いろんなところでチュートリアルが公開されていますが、チュートリアルごとにやり方が違うこともある。自由にできることはいいんですが、大きなシステムでルールを決められないと、混乱してしまうことがあります。

よく言われている例として、インポートの順番をずらすと、起動しなかったりうまくいかないといったケースがあります。Pythonに詳しい人であれば解決できるでしょうが、比較的自由だからこそフォルダ構造とかを自由に組めてしまうので、混乱気味の場合もあります。

機能についてです。DjangoにあってFlaskにないものとして、まず、ログインのファンクションがない。自分で書くか、アドオンを見つけてくる必要がありますが、いいアドオンを私は知りません。それから、ORM……データベースの世界だと、SQLAlchemyを使うのはよくあるパターンです。データベースがいらなければもちろん使わないみたいな感じですね。

WSGIに対応しているので、デーモン管理はしません。アドオンはFlaskのアドオンがあるということです。

ハンドリングのローカルデータがちょっと特徴的で、グローバルな変数になっています。from flask import gとかで、gの中にいろんなものを突っ込んでおいて、いろんなモジュールから呼び出すと、ローカルスレッドで提供されてきます。これは使い出すと便利です。import gとやっておけば、gの中からまた持ってきたらローカルスレッドでちゃんとデータをもらえるので、テストコードを書いているとちょっと楽だったりして、ごまかしているような気分にもなるんですけど、便利です。

Asyncには対応していなくて、環境変数はPythonコードでもiniファイルでも書けます。

フルサポートなWebフレームワークPyramid

次はPyramidです。(自分の服を指して)今、私が着ているこれ、PyramidTシャツです。海外のPyramidの人たちが配ったり売ったりしているものです。

私はDjango、Flask、Pyramidの中だとPyramid派閥で、Pylons Projectというところにいます。実際には去年いろいろ動きがあって、ちゃんとFoundation組織に属そうということになって、今はPlone Foundationの中に入ったか入ろうとしているかというところで、これからはFoundation組織でリリースをちゃんと管理していこう、作っていこうと考えています。

Repoze Public Licenseという、少し変わっていますが、BSD-likeのライセンスです。1.0のリリースは2011年です。この前身にPylons Project、Pylonsがあって、いろんなWebのエンジニアたちが再集合していたので「フレームワークがいろいろ乱立しているけど、もう1回Pylons Projectの中で全部やってピラミッドみたいなものを作ろう」という動きがあって、Pyramidというかたちになっています。

最新バージョンは1月1日現在で1.10.1です。特徴は、フルサポートなWebフレームワークです。いろんな機能をフルサポートしています。

いいところは、真面目。真面目に作らないといけない。さっき、Flaskは自由にポンポン簡単に作れると言いましたが、Pyramidでそうやって作るともっと難しくなってしまいます。ちゃんと真面目にきちんとこうやって作りましょうというところが特徴です。

逆に、そういう意味ではラーニングコストが高い。Flaskを知っている人が、いきなりPyramidを使いました。「これってどうやってやるんですか?」「ドキュメントの後ろに書いてあるけどね」と、そういった感じになっちゃうところが、ちょっと「あれ?」となるところです。ただ、真面目に作れるシステムは良いと言われています。

機能面は、Flaskに似ていますが、ログイン機能などはあります。ORMはSQLAlchemyが一般的です。変わり種としては、歴史的なものもあるんですが、ZopeのZODBというオブジェクトデータベースとの接続ができることです。REST APIについては、アドオンがないわけではないと思うんですけど、なかなか良いものが見つけられないので、私も自分で書いています。

ここはZopeとかが使っているcontextオブジェクトという、リクエストが発生したときのcontextというものを管理して、それにいろんなデータやオブジェクトが入るという仕組みです。このへんは歴史的にもそういうふうになっています。Asyncにも対応しています。セットアップはiniファイル形式です。

フルスタックな巨大なWebフレームワークZope

ここまで、3つのフレームワークを紹介しました。だいたいこの3つをよく比較するんですが、それ以外の6個はなにかというお話をします。

Zopeは、極端にいうとPythonがZopeという世界から生まれてきた。Zopeの中には、標準ライブラリのdatetimeとは違う、DとTが大文字のDateTimeがあるんです。なぜかというと、Pythonでは昔、標準モジュールにdatetimeがなかったから。とくにPEPがなかった時代からあるので、当然PEP8には則っていないとか歴史的な、そういう意味ではこういうところからいろいろなものが作られていったり、これが標準で入ってたり、いろんなものがあります。

Zope Foundationという組織があるんですが、今はそれも解体して、全部Plone Foundationにマージしようという話になっています。ZPLというZope Public Licenseというものです。

最初のリリースは2000年より前です。2000年以前の資料はなかなか見つけられないですね。最新は2.13.28ですが、実は4.0を作っています。Zopeの歴史には3.0もあったんですが、3.0と2.0の差がありすぎて結局2.0を使い続ける人たちが多かったので、3.0を飛ばして4.0がリリースされました。4.0の第一目標がZopeのPython3対応だったんです。すごく大変だったんですが、ようやくこれもリリースされて、またZopeを使える世界になりました。

一言でいうと、フルスタックな巨大なWebフレームワークです。コンテンツの階層管理ができることと、強力なセキュリティ機能を持っていることが特徴です。でも、ちょっと重かったり難しかったり、歴史的にいろんなものがあるので、気楽にポンと使えるかというと、なかなか大変かもしれません。

だいたいの機能を備えていて、ZODBというデータベースまで持っています。これぞフルスタック! サーバも、最近はWSGIに対応しましたが、オリジナルでデーモン管理もできます。だいたいのことはできるフレームワークですが、最近の軽量化やコンテナで動かす、Lambdaで動かすといったサーバレスみたいなものからすると、やや古い感じはします。

非同期Webフレームワークの定番Tornado

次はTornado。もともとFriendFeed……現Facebook社が作ったものです。Facebook社のほうでApacheライセンスです。2010年にはもうありました。非同期Webフレームワークの定番ですね。

いいところは、非同期をサポートしている定番的なフレームワークです。微妙なところは、やはりやや難しい感じがします。非同期自体なところの難しさもありますが、ちゃんといろんな機能が入っているというところで、難しいと思います。

テンプレートがオリジナルだったり、Asyncは対応していたりしますが、Webサーバもオリジナルですね。この辺がなかなか難しいかもしれない。ただ、非同期にしたければTornadoを使えと、つい最近まで言われていました。

それで、そんなところから出たaiohttp。これもAIOの世界がPython3の標準のライブラリに入ったわけです。Pythonの3.3とか3.4くらいからかな。こういうものでApache 2のライセンスで、2013年に出ました。最新バージョンは3.5.1です。非同期のHTTPクライアントとサーバで、ライブラリ群に近い小さな部品がいろいろあって、組み合わせて使います。

シンプルな非同期サポートがいいところです。微妙な点としては、機能が少ないので、作るものが多くなる。ただ、機能をそんなに作らないのであれば便利です。

今言った通り、機能が少ないです。テンプレートもaiohttp_jinja2を使って、environmentの機能もなくて、そこにちゃんと環境変数があるならos.environで取るとかそんな感じです。本当に小さなライブラリ群というとらえ方でいいと思います。

オブジェクトモデルの非同期なREST APIフレームワークGuillotina

Guillotina。これはみなさん知らないと思います。先ほどから、私がずっとPloneと付き合っている人間なのでPloneの話やZopeの話が多いんですが、Plone Foundationがベースになって、plone.serverという名前でもともと作り始めたんですが、Ploneだけではなくいろんなものに向かっていこうということでBSDライセンスで作っているものです。

私はオブジェクトモデルの非同期なREST APIフレームワークと言っています。オブジェクトモデルは、そのオブジェクトの階層化、Zopeから来た階層化みたいなものをCMSで作るときに便利なので、それをAPIでも実現しようとしています。コンテンツの階層ができて、高いパフォーマンスを生み出している。

ただ、事例が少ない。オリジナリティが強いんですね。そのぶん、どうやって使うか、どんなふうに学んでいくか、どうやってメンテナンスをしていくかという点が少しつらいかもしれない。

オリジナルのサーバがあるので、Runコマンドとかももちろん入っていますし、Async対応になっています。バックエンドはPostgresを使います。CockroachDBも使えるらしいんですけど。スペシャルなコンテナをPostgresの中に入れるので、PostgresにSQLを叩いてもなにが入っているかよくわからない状況になっています。オブジェクトトラバーサルとかがあります。

軽量なマイクロフレームワークBottle

Bottle。すごく小さな軽量なマイクロフレームワークです。MITライセンスで出ています。2009年に登場しました。1ファイルで簡単なものを作るときに使われることが多いです。

いいところは、すごくシンプルです。逆に、機能が少ないので、難しいことをやろうとするときは、自分でちゃんと機能を作れる前提でやることになります。ORMでつなぐ・つながないみたいなところとか、テンプレートエンジンとかもアドオンだったりします。

シンプルだが事例が少ないresponder

最後のフレームワークが来ましたね。responderを知っている人?

(会場挙手)

3、4人ぐらいいますね。responderね……私は、この先不安が強い感じがしています。Kennethさんという、日本にも2014年ぐらいに来た有名な方が作っているんですが、最近の活動もちょっと見えなくなっていて、少し心配です。いいところは、シンプルです。ただ、事例が少ない。ひょっとしたら、ないんじゃないかと思うぐらい少ない。けっこうバッと知られたんですけど、ちょっと先行きが不安という感じはしています。正直わからないところもあります。

他はなにがいいの? というと、今日のリストには載せていませんでしたが、実はStarletteというフレームワークがあって、ASGIに対応したAsyncのサーバを作るならこっちのほうがいいんじゃないかとよく言われています。Flaskに似ていて、FlaskのAsync対応版みたいだという評判です。

これもまだできたばかりなので、そんなに情報がないかもしれないですが、新しいものをすぐに追っかけたいのであれば、こういうものもありだと思います。

プロジェクト、フレームワークの選び方

最後のトピックになりました。「プロジェクトでどのようにフレームワークを選ぶのか」。私の場合ですね。

ニュースサイトのように、記事が多くて階層化する場合を考えます。タグ付けやカテゴリ管理、記事をもう1回再編集するというような管理機能、ログインさせてユーザ管理をする機能、閲覧制限が必要な場合に制限する機能など、ニュースサイトはけっこう機能が多いです。

私だったら、Django、Pyramid、Zopeのどれかを選びます。Flaskでは嫌だなという感じです。階層化があるのでPyramidとかZopeとかが向いていますが、頼りすぎるとなかなかツラくなる場合もあるので、Djangoという手もあると思います。

バックエンドのAPIサーバを書く場合を考えます。JSONを効率良く返したいわけですね。単機能で作れる場合もある。機能の多さでフレームワークをある程度選ぶ必要がある。そうすると、私は通常だとDjango、Flask、Pyramidあたりを選びます。他のものでも、非同期をしたいとか、もうちょっと軽くていいので機能を本当に分けたい場合だとBottleで作ろうなどと考えます。

1個だけのエンドポイントのAPI……2個でもいいんですが、エンドポイントがすごく少ないAPIサーバを作る場合を考えます。JSONを効率良く1個だけ書いて、あとは単機能でいい。データを持たないかもしれない。データベースとかもいらないかもしれない。ただなにかを計算して返すだけかもしれない。そういうとき、Djangoは絶対に選ばないです。

Flaskみたいな簡単なものとか、aiohttpとかで簡単に作っちゃうとか、Bottleでいいんじゃない? と言います。AWS Lambdaで動かすとなるとAIOにする必要がないので、そうするとこのaiohttpが消えちゃったりするんですね。Lambda自体が、ファンクションが複数立ち上がってくれるわけですから、そこで1つ処理をしたらなくなるような仕組みにすると大きなサーバを持っている場合とは考え方も違うと思います。

ポータルサイトを作る場合を考えます。ログインが必要で、階層化になって、タグ付けがあって、コンテンツ管理で閲覧制限が必要となると、ふだん使っているという理由でZopeを挙げますが、もちろん他のものでもいいと思います。私だったらDjangoやPyramidなどを選びます。

コンテンツ管理システムを作る場合を考えます。全文検索機能を入れたいとすると、Elasticsearchや、Solrを一緒に使おうという話があると思うんですね。もちろんそれでいいと思いますが、もっと気軽にやるなら、Zopeなら最初から入っています。これぞオールインワンですね。だから使えというわけじゃないですが。

ElasticsearchとDjangoを組み合わせるという話は去年のトークで池内さんという人が話しましたが、なにが難しいかというと、コンテンツ側のデータベース、SQLデータベースにデータをなにかポンと入れました。そのときにElasticsearchにもデータを入れなければいけない。そうすると、2フェーズコミットをしないといけなくなる。

例えば、Elasticsearchだけ落ちてしまうと検索に引っかからなかったり、逆にElasticsearchにだけ残ってしまうと検索に引っかかってしまったりするので、インデックスを作り直さなきゃいけなくなるんです。実際そういう仕組みを作るのは大変なわけです。これはちょっと方法があるので、それを使ってやります。

APIサーバ、CMSの場合はGuillotinaですね。Plone FoundationのアンバサダーということもあってGuillotinaを推していますが、私もまだ実際には使っていないので、みなさんと一緒に勉強したいと思います。

それでは、お聞きいただきありがとうございました。

(会場拍手)

Q&Aの前にちょっとだけ。このコンテンツは@aodagさんと、@c_bata_さん、Jonasさん、よく一緒に勉強会をやったりしている3人なんですが、彼らにレビューしていただきました。本当にありがとうございました。お礼を言わせていただきます。

バージョンアップがつらい人へのおすすめフレームワーク

ということで、どなたかご質問ありますか? 私、バーッと捲し立てちゃうので、Q&Aが出にくいんですよね。

質問者1:発表ありがとうございました。ユーザ管理をしてコンテンツを見るようなサイトを作りたいと思っています。フレームワークがバージョンアップしたときに、ついていくのがツラいんですが、そういうルーズな人へのおすすめはあるでしょうか?

寺田:難しいご質問ですね。私もバージョンアップはいつも悩みどころです。例えばDjangoだと、Djangoのバージョンアップの方法があるので、比較的安心してバージョンアップしていけるとも言われていますが、もちろんそれなりの痛みは伴います。私はZopeを使ったPloneというものをずっと使っていますが、やはりバージョンアップはすごく大変です。

そういう意味で、きっちりリリースがされていくことも1つの指標かと思います。例えば、今回Python2からPython3になるときに、(Python3に)なれていないフレームワークも当然あるわけです。そうすると、そのバージョンになってくれないとセキュリティ問題が出ちゃうので、バージョンアップができない。

もちろん、バージョンアップのステップを提供していないフレームワークもあるので、そこをすごく慎重に選びます。Djangoはその点、定評があるほうですね。Flaskは、データベースを自分でそんなに持っていないですから……自分でマイグレーションを考えるとか、変わり身が早いフレームワークと変わり身の遅いフレームワークがあるので、Flaskはそんなにたくさんバージョンアップされないし、昔のものでもけっこう動くというところがあるかもしれません。でも、慎重に選ばないとなかなか大変ですよね。

アドオンの選び方

他に質問あれば。では、後ろの方どうぞ。

質問者2:発表ありがとうございました。フレームワークはだいたいエクステンションの機能があると思うんですが、僕はFlaskとPyramidを何個か見たところ、エクステンションでデファクトというというものがわかりにくい、乱立しているような印象があって、そのあたりを選ぶときに考えることはありますか?

寺田:アドオンの選び方ですよね? ものすごく難しいですよね。フレームワークを選ぶより難しいかもしれません。このアドオンにしていいのかどうか。それはPythonのパッケージのライブラリをなにか使う……NumPyなら安心だよねと思うけど、他のものは大丈夫? と思うわけです。

それは同じことだと思っていて、選び方は本当に難しいです。やはり、実績があるもの、こういうところで長く使われているもの、開発者が信頼できるものということを、私は基準にしています。やはりこういうことは、たくさん使っている人がちゃんとした情報を持っているので、例えばこういうPyConでいろいろ聞くことも1つの方法だと思いますし、勉強会に行ったり、Twitterでそういう人を追っかけたりしてもいいと思います。

私もたまに「IPアドレスを解析するためのライブラリってなにかない?」という感じで、TwitterとかFacebookでポンと聞いて、詳しい人に「俺はこれで問題あったよ」とか「問題なかったよ」と言われると安心というところがあります。

質問者2:ありがとうございました。

寺田:1つだけ、選び方のポイントです。長くちゃんとメンテナンスされていくかとか、ライセンスはもちろん大事ですが、私は誰がリリースしているかも見るようにしています。個人でやっていて、一人だけの力だと、長くメンテナンスされない可能性があるわけです。当然、DjangoのようにPloneとかのFoundationだと、長くメンテナンスされる可能性が高い。

けれども、動きが早いかとか新しいものがすぐに入るかという点では、Foundationの中で議論をしてから出すことになるぶん、遅くなる可能性がある。でも安心したマイグレーションステップが提供される場合もある。そういうところで、誰がリリースしてどういうライセンスなのかという点が1つ。

もう1つは、周りに詳しい人がいたら、やっぱりその人に聞くことです。ベテランの人、一緒にやっていく人に聞く。

例えば、会社の全員がDjangoを使っているのに「私はFlaskに変えたいです」と言ったとします。その人が本当にFlaskを好きで、Flaskをわかっていれば変えられるかもしれないけれど、「いや、私これから勉強していくんです」みたいな人が「ちょっとFlaskを勉強してFlaskのことがわかるのでやらせてください」と言っても、絶対に行き詰まりますよね。Djangoならそこまでわかっている人がいるのに。まわりの環境も1つあると思います。

司会者:時間になりましたので、セッションを終了させていただきます。寺田さん、ありがとうございました。

寺田:ありがとうございました。

(会場拍手)