どうも、ご無沙汰していました、機械です。
最近、様々な理由からPyPageをいじりだしています。
PyPageは、Pythonで書かれた小規模・軽量が売りのWeb
サーバです。
そのためか、ソース内に埋め込まれたドキュメントと
サンプルだけ以外には、ほぼドキュメントらしいドキュ
メントも解説も存在していないようです。
実際、作者が日本の方ですし、内部ドキュメントは詳
細で判りやすいので、「Pythonテクニカルリファレンス」
あたりを片手にハッキングしていけば、理解できないよ
うなコードは無いようなのですが、「気軽に使える」と
いう魅力を若干生かしきっていないようなのが気になり
ます。
というわけで、「PythonとHTMLの基礎さえ知ってれば、
ある程度は使える」程度に、PyPageの使い方を紹介して
いきたいと思います。
■その前に・・・Webサーバってナニ?
え〜、TSNETのMLにご参加の方で、よもやWebサーバを
ご存知無い方などいるはずない・・・と、お思いでしょ
うが、事実私自身が知らなかった(爆)ので、念のためち
こっと説明しておきます(私だけかもしんないけど)
Webサーバは、IEとかネスケのようなブラウザをクライ
アントとして、両方でハイパーテキストデータベースを
実現するアプリです。ところが、こういったブラウザは、
単独でOSのファイルシステムにアクセスして、ローカル
ファイルを表示したり、リンク・ジャンプをさせたり、
果てにはJavaScriptのようなスクリプトやJavaアプレッ
トのようなプログラム(Flashモジュールとか、もかな?)
まで動かしてしまうので、単なるファイルサーバとどこ
が違うのか、といわれると、実は結構悩んだりします。
で、一口に言えば、Webサーバを立てると、CGI(Common
Gateway Interface)スクリプトや、SSI(Server Side
Include)スクリプトが使えるページが動きます。
Javaアプレットや各種HTMLスクリプトは、基本的には
クライアントサイド(ページをダウンロードしたマシン
の上)で実行されますので、セキュリティ管理のため、
ファイル管理などにかなり大きな制限があります。
しかし、サーバサイドのスクリプトなら、その制限は
事実上ありません。
無論、インターネットに公開するようなWebサーバを立
ち上げるなら、それなりの知識や技術も必要ですが、HTML
コンテンツをフロントエンドにしてアプリケーションを
作ったり、あるいはLAN内での閲覧用コンテンツを立ち上
げたりと、あまりセキュリティーに目くじらを立てるよ
うなものでない場合は、結構気楽に使えます。
■PyPageとは?
PyPageとは、標準モジュールのみを使用して書かれた、
PythonスクリプトによるWebサーバです。
現在、Pythonで書かれている最も有名(日本では、多
分Python本体よりも有名)なWebアプリケーションサーバ
は、ご存知Zopeでしょう。
というわけで、PyPageの特徴をざっと知っていただく
ために、ざっとZopeと比較してみました。
・機能
Zope :豊富
PyPage:最小限度
・マシンパワー
Zope :やや必要
PyPage:軽い
・コンテンツ作成
Zope :Web上で可能
PyPage:テキストエディタで地味に・・・
・Webページ上のPythonスクリプト
Zope :DTMLに組み込み可能
PyPage:不可
・PythonによるCGI/SSIモジュール
Zope :可能だが、手続きがやや面倒
PyPage:簡単。ただし、安全性に要注意
・OS依存
Zope :若干あり
PyPage:ほぼ無し
雰囲気としては、ZopeがWebアプリケーションサーバと
して、独立した存在であるのに対し、PyPageは、Python
を用いた動的Webコンテンツのためのフレームワークとい
った印象があります。
何にしても私にとって嬉しいのは、ローパワーで動く
軽量さと、あまり規約を気にせずにPythonで書かれたモ
ジュールを追加できる自由度にあります。
それでは、PyPageのさわりの部分を、紹介したいと思
います。
<注意>
この文章に掲載したスクリプトは、セキュリティや安
定性に関して、かなりはしょってあります。「動く」実
感以上に、ちゃんとしたスクリプトを書かれる場合は、
PyPage付属のサンプルのソースをご参照ください。
■PyPageの立ち上げと、「はじめてのPyPage」
それでは、使い方です。
まず、PyJUGのページ(http:www.python.jp/Zope/)から
たどって、PyPageのアーカイブファイルをダウンロード
してきます。
解凍したフォルダ(ディレクトリ)の中のうち、OSにあ
わせて以下のように起動させます。
UNIX系の場合は、startd.pyかminserver.pyスクリプト
を起動させます(Mac OS XはUnix扱い)
Winの場合、NT系(NT4.0,2000,XP)なら、コンソールか
らminserver.pyを立ち上げても良いのですが、マルチプ
ロセスがサポートされていないWin9x系(95,98,ME)の場合
は、Tkを使ったコンソールが立ち上がるstart.pywをダブ
ルクリックして立ち上げた方が、終了させるとき気楽で
しょう。
PyPageを立ち上げたら、Webブラウザから、
http://localhost:8000/にジャンプしますと、トップペー
ジにアクセスできます(もしこれでアクセスできない場合
は、http://127.0.0.1:8000/からアクセスできます)
トップページはpubフォルダ下のindex.htmlですので、
このファイルを書き換えればトップページが変更されま
す。
そこのサンプルやソースを適当に閲覧したら、次に、
実際にPyPageモジュールを作ってみましょう。
まず、pubフォルダ下に、test0.pyという名前でファイ
ルを作り、以下のように書きます。
#---test0.py---
def page(pc):
pc.send_head()
pc.write('''<html>
<head>
<title>Hello</title>
</head>
<body>
<h1>Hello PyPage for Python!</h1>
</body>
</html>''')
#---test0.py---
これで、http://localhost:8000/test0 にアクセスす
ると、コンテンツが表示されます。
HTMLファイルではなくPythonモジュールを指定される
と、PyPageはモジュール内のpage関数を探してそれを実
行します。
ページは動的に生成されてブラウザに送られます。
ちなみに、http://localhost:8000/test0.py と拡張子
つきで指定すると、Pythonのスクリプトソースが表示さ
れてしまいますので注意してください。
page関数の第一パラメータはPyPageContextインスタン
ス(要するにページそのもののオブジェクト)になるので、
このページオブジェクトにsend_headメソッドで、まずヘ
ッダを送ってやり、次にコンテンツ内容をテキストで書
いてwriteメソッドでページオブジェクトに送ってやれば、
そのコンテンツが表示されます。
※コンテンツって、「内容」って意味だから、「コンテ
ンツ内容」って言葉はかなりヘンだけど・・・
■動的ページを作ってみる
とりあえず、動的ページを実感すべく、カウンターと
日付や時刻でも入れてみましょうか?
#---test1.py---
from time import ctime
page_context='''<html>
<head>
<title>Time and Count!</title>
<style>
p{font-size:48pt;text-align:center;color:red}
</style>
</head>
<body>
<p style="">Hello PyPage for Python!</p>
<p>TIME=%(time_now)s</p>
<p>COUNT=%(count_now)d</p>
</body>
</html>'''
cnt = [1]
def page(pc):
pc.send_head()
time_now = ctime()
count_now = cnt[0]
cnt[0] += 1
pc.write(page_context % vars())
#---test1.py---
文字列オブジェクトに対する % 演算子の拡張表記は、
シーケンスではなく辞書で変換文字のデータを渡せるた
め、スコープ領域の全オブジェクトの辞書を作るvars組
み込み関数と併用すると便利です。
※上の例では、%(time_now)sにtime_nowの内容が、
%(count_now)dにcount_nowの内容が、それぞれ渡され
ます。
カウンタをグローバル変数にするのはなんかヤなので、
リスト参照にしてポインタっぽく使ってます。
以上、page関数が呼び出された際、文字列を逐次変換
させ、現在値を表示するという非常に簡単な仕組みで、
見た目も動的なページが出来上がりました。
■フォームからリクエストを受け取る
さて、入力フォームから値を受け取り、それを用いた
表示を行う、という例を行ってみましょう。
入力フォームのほうは、別に動的にする必要も無いの
で、ここでは素直にHTMLドキュメントを書きます(ファ
イル名はtest2.htmlとでもしましょうか)
<html>
<head>
<title>Form Test</title>
</head>
<body>
<form action="test2b" method="post">
お名前は?<input type="text" name="uname" />
<input type="submit"/>
</form>
</body>
</html>
次に、名前入りのメッセージを自動生成します。
メッセージが日本語コードでやりとりされるので、コー
ド変換を行います。
#---test2b.py---
j_mes = unicode("%(u_name)sさん、こんにちは").encode("UTF-8")
page_content='''<html>
<head>
<title>Hello!</title>
</head>
<body>
<p>%s</p>
</body>
</html>''' % j_mes
def page(pc,uname):
u_name = unicode(str(uname)).encode("UTF-8")
pc.send_head()
pc.write(page_context % vars())
#---test2b.py---
フォームから送られたメッセージは、page関数の引数
としてキャッチされますので、そいつを文字列化してや
ると、メッセージが取り出せるわけですが、ASCIIコード
でない場合は、UNICODE変換を掛けておくほうが無難です
(UNICODEで送られてくるという「滅多に無い」状態を期
待するより)
フォームからの情報は様々ですが、とりあえずテキス
トやラジオボタンからの情報程度なら、上記のようなコー
ドを書けば十分です。
なお、<input type="file">のような厄介な形式の場合
については、付属のサンプルスクリプトにありますので、
参照してみてください。
さて、もう少し書きたいことがあるのですが、やや長
くなりましたので、今回はこのへんにしておきます。
/機械伯爵/