WSGIとPythonでスマートなWebアプリケーション開発を

第1回WSGIの概要

PythonのWebアプリケーションフレームワーク

Pythonには、Zope、Twisted、Django、TurboGearsなどのさまざまなWebアプリケーションフレームワークが存在します。以前は、このような幅広い選択肢は、新しくPythonを使用しようとするユーザにとって都合が悪いことがありました。使用するフレームワークによって、利用可能なサーバが制限されてしまったり、逆にサーバによって利用可能なWebアプリケーションフレームワークが制限されるといったことがあったためです。

そのようなPythonの状況とは対照的に、Javaにおいては、多数のWebアプリケーションフレームワークがあるにもかかわらず、サーバとWebアプリケーションをつなぐ際に、統一されたJava Servelet APIを用いることで、アプリケーションフレームワークを気にせずにServelet APIが利用できる環境で動作させることが可能です。

このような、サーバとWebアプリケーションをつなぐ共通のインターフェースをPythonで定義したものが、PEP333日本語訳版WSGI(Web Server Gateway Interface)です。

WSGIの概要

WSGIはJavaにおけるJava Servelet APIと同じように、WebサーバとWebアプリケーション間の汎用的なインターフェースを定義しています。WSGIを利用することで、WebサーバとWebアプリケーションの実装を切り離すことができ、WebサーバとWebアプリケーションフレームワークの組み合わせを柔軟に選択することができるようになりました。

WSGIをサポートしているWebアプリケーションであれば、 WSGIをサポートするWebサーバで容易に動かすことができます。Apacheを使用していてmod_wsgiモジュールが利用可能なサーバであれば、WSGIアプリケーションを直接実行できます。

また、サーバ側でmod_wsgiモジュールが提供されていなくとも、WSGIアプリケーションをCGIとして動作させるためのモジュールがPython(Python2.5以降)に標準で組み込まれているため、少しのコードを追加するだけでCGIとして動作させることができます。

WSGIは、現在では、

  • Twisted
  • Zope(Ver.3から)
  • CherryPy
  • TurboGears
  • Django
  • Pylons

などのWebアプリケーションフレームワークで利用されています。

たとえば、Zopeはそれ自体がWebアプリケーションサーバとして動作する非常に大きなフレームワークです。 Zope2までは、Webアプリケーションサーバとして動作させることしかできず、サーバ上で動作させるには新しくサーバプロセスを立ち上げなければいけませんでした。そのために、Zopeはサーバプロセスが追加できるサーバでなければ動作させることができませんでした。しかしZope3になると、Zope自体をWSGIアプリケーションとして動作させることができるようになり、サーバプロセスを立ち上げられないサーバでも動作させることができるようになりました。

Hello, world アプリケーション

WSGIで定義されているWSGIアプリケーションのインターフェースは非常にシンプルです。文章で説明をしてもわかりにくいと思いますので、まずは小さなWSGIアプリケーションを見てみましょう。

リスト1
def application(environ, start_response):

    start_response('200 OK', [('Content-type', 'text/plain')])

    return 'Hello, world'

たったこれだけです。関数が1つしかありませんが、WSGIの仕様に準拠した立派なアプリケーションです。

まずはこのアプリケーションを動かしてみます。リスト1に少し付け足し、リスト2のように書き換えます。

付け足した部分は、WSGIアプリケーションを実行するためのサーバを動かす部分です。サーバとしてPython 2.5から新しく標準ライブラリに追加されたwsgirefモジュールを使用しているので、実行にはPython2.5以上が必要です。

リスト2
def application(environ, start_response):

    start_response('200 OK', [('Content-type', 'text/plain')])

    return 'Hello, world'


from wsgiref import simple_server

if __name__ == '__main__':

    server = simple_server.make_server('', 8080, application)

    server.serve_forever()

リスト2をsample1.pyとして保存し、pythonコマンドで実行してください。

図1
$ python sample1.py

そして Web ブラウザでhttp://localhost:8080/にアクセスします。正常に実行できていれば「Hello, world.⁠⁠ と表示されます。

1行ずつ解説していきます。

リスト3
def application(environ, start_response):

application関数は、environとstart_responseという引数を持っています。

environにはWebサーバからPython組み込みの辞書型オブジェクトが渡されることになっています。辞書の中には、Webブラウザなどのクライアントから送られたリクエストの情報などが入っています。start_responseは、2つの必須引数と1つのオプション引数を持った呼び出し可能オブジェクトが渡されることになっています。

リスト4
start_response('200 OK', [('Content-type', 'text/plain')])

start_responseに2つの引数を渡して呼び出しています。

第1引数の'200 OK'はHTTPのステータスコードです。リクエストを処理した結果に応じて'404 Not Found'などを返すようにしなければなりませんが、今回は簡単のために'200 OK'しか返していません。

第2引数はHTTPのレスポンスヘッダです。(ヘッダ名, 値)というタプルのリストを渡します。

リスト5
return 'Hello, world'

application関数の返り値として、'Hello, world.'という文字列を返しています。この返り値はHTTPレスポンスの本文として扱われます。アプリケーションは、反復可能なオブジェクト(iterable object)を返さなければいけません。また、反復した結果として、文字列オブジェクトを返さなければいけません。

反復可能(iterable)なオブジェクトとは、 ⁠for n in x:」というfor文の x の部分に使用できるオブジェクトで、 __iter__ というメソッドを持っているものです。反復可能なオブジェクトには、リスト、タプル、辞書、文字列などがあります。また、ユーザ定義のクラスであっても、 __iter__ メソッドを定義することで、iterableオブジェクトとして扱われます。

以上がWSGIアプリケーションの仕様です。

まとめ

WSGIアプリケーションの仕様をまとめると

  • 2つの引数を持った呼び出し可能なオブジェクト
  • 第2引数として渡されたオブジェクトにHTTPステータスコードと[(レスポンスヘッダ, 値)]という値を渡して呼び出す
  • 返り値にiterable objectを返す
  • 返り値のiterableをiterateすると、文字列を返す

を満たすオブジェクトが、 WSGI アプリケーションです。

今回作成したHello, Worldアプリケーションは、非常に簡単なアプリケーションですが、 WSGIの基本的な仕様を満たすアプリケーションになっています。しかし、実際のアプリケーションは、ユーザからの入力を受け付ける、入力されたデータを処理する、結果をユーザに返す、というような流れがあります。次回はもう少し実際的な例として、メッセージボードアプリケーションを作成し、フォームの入力の取得や、動的ページ生成について説明します。

呼び出し可能なオブジェクトとは、関数のようにx(arg1, arg2)などと、引数を渡して呼び出せるオブジェクトです。呼び出し可能なオブジェクトには、関数やクラスなどがあります。また、ユーザ定義のクラスでも、 __call__(self, arg1, .. , argn) というようなメソッドを定義することで、呼び出し可能なオブジェクトになります。

おすすめ記事

記事・ニュース一覧