一昨日紹介した第5回PostgreSQLアンカンファレンス@東京で聞いたPL/PythonでBottole(アシストY田さん、スライドはこちら)を自分もやってみたくなり、とりあえずWebサーバ起動・停止だけですがWindows + Python3.3で試したら一応できました。Webサーバ停止はStack Overflowでのやり取りを参考に、ブラウザから特定のURIをリクエストするとPL/Pythonの関数が終了するようにしました。
[実行環境]• Windows 7 32bit• PostgreSQL Portable 9.4.1(サービスでなく、バッチファイルで起動するポータブル版)
• WinPython 3.3.5
• 上記の環境でPL/Python3を準備する過程:5月19日の記事を参照• ユーザ:管理者権限のない標準ユーザアカウント
• Bottle: Python Web Framework 0.13-dev
↓PL/PythonでBottleを動かし、テストページを表示したところ。PostgreSQLを起動したコンソールにBottleのメッセージやログが出て、一時的にWebサーバを内蔵した感じです。using WSGIRefServerとあることから、自分も前に試したWSGI用の標準モジュールが使われていると判明。
準備
Bottleは、http://bottlepy.org/docs/dev/tutorial.html#installationの冒頭にある»http://bottlepy.org/bottle.pyをダウンロードすると最新の0.13devで、これをWinPython下のLibフォルダにコピーしました。ファイル一つのフレームワークなので超簡単。次に、ポータブル版PostgreSQL 9.4でPL/Python3を使えるようにする過程は、先ほど実行環境の所に書いた5月19日の記事のとおり。データベースをバッチファイルで起動したところが ↓ の画像です。後からPL/Rも使えるようにしたのでRのバージョン等が出ていますが、今回は関係ありません。
適当なデータベースを作り(今回はplpyという名)CREATE EXTENSION plpython3u;でPL/Pythonをインストールしたら ↓ 準備完了。

無名コードブロック(DOコマンド)でBottleを起動・終了
今回はデータベースに何も作らず、下記の無名コードブロック(無名関数を実行できるDOコマンド)をエディタで書いてpsqlに貼り付けました。$py$~$py$がPythonのコードで、前半はBottle公式サイトのトップページにあるHello Worldそのまま。後半はWebサーバの停止処理で、/close_from_browserにアクセスがあったらPython内で例外が発生して無名関数が終了し、結果としてWebサーバが止まります。データベースサーバには特に影響しません(時間のかかる処理が、途中で失敗したのと同じ)。
DO LANGUAGE plpython3u $py$
import sys
from bottle import route, run, template
@route('/hello/<name>')
def index(name):
return template('<b>Hello {{name}}</b>!', name=name)
@route('/close_from_browser')
def close_from_browser():
sys.stderr.close()
return
run(host='localhost', port=8080)
$py$;
正攻法ではありませんがsys.stderr.close()と打って標準エラーを閉じるとBottle(というかWSGIサーバ)が止まるのは、下記で知りました。stopメソッドがないけどどうしたらいい?という質問と回答。ちゃんとした方法もいくつか載っていて、当初はそれらを試したものの動かず、最後にダメ元でやってみたらできたという顛末です。
»Stack Overflow : Bottle web framework - How to stop?
動作の画面
上の無名関数をpsqlで実行すると ↓ のようにずっと終了しない状態になり、関数の内部でWebサーバが待ち受けします。ブラウザを開いてhttp://localhost:8080/hello/(任意の文字列)をリクエストすると、二つ目の画像(冒頭の再掲)のように応答しアクセスログが出ます。
↓ 存在しないURIをリクエストすると、初めからBottleに備わっている404 Not Foundのページが表示されます。このあたりがWebフレームワークの便利なところ。
↓Webサーバ停止のためhttp://localhost:8080/close_from_browserをリクエストすると、例外が発生し無名関数が終了します。無理矢理な止め方ですが、データベースには影響しないのでとりあえず良しと。もう少しスマートに、例外を捕捉して関数を正常終了できないか、今後試します。
↓ 以上のWebサーバ起動・終了の後、PostgreSQL本体を再起動した様子。Webサーバを走らせるPL/Pythonの関数が停まってない状態だと、通常のデータベース終了自体ができずimmediateモードでの終了だけが可能で、次の起動時に復旧処理(REDO)が走りますが、今回はそういうことはなく普通に終了・再起動ができました。