はじめに
PythonでWebサーバを起動する方法を学んだので、アウトプットする目的で投稿します。
どなたかの参考になれば、幸いです。
本稿では標準ライブラリであるhttpモジュールやurllibモジュールは取り上げず、bottle、Flaskを使用したサンプルコードを元に説明します。
また、ApacheとPythonスクリプトを接続する方法についても説明します。
環境
- Windows 10 home
- Python 3.7.4
WSGI
PythonでWebの勉強をしているとWSGIという言葉がよく頻出します。
WSGIはPythonのWebアプリケーションとWebサーバーの間の標準化されたAPIのことを指します。
PythonのWebフレームワーク、Webサーバの多くはWSGIを使っています。
フレームワークやサーバの開発者以外がWSGI自体の仕組みを知る必要性は高くないことが言われています。
これから取り上げるフレームワークはすべてWSGIを使用しています。
Bottle
Bottleは1つのPythonファイルだけから作られているので、非常に試しやすく、デプロイが容易です。
次のコードでWebサーバを実行し、 http://localhost:9999 にGETメソッドでアクセスしたとき、レスポンスを返します。
前準備としてBottleをインストールしましょう。
$ pip install bottle
from bottle import route, run
@route('/')
def myhome():
return "It's my home page"
run(host='localhost', port=9999)
$ python bottle1.py
Bottle v0.12.18 server starting up (using WSGIRefServer())...
Listening on http://localhost:9999/
Hit Ctrl-C to quit.
http://localhost:9999 にアクセスします。
ステータスコード200で、ボディに It's my home page と表示されており、レスポンスの内容がわかります。

サーバ側では、以下のように出力されています。
127.0.0.1 - - [17/Dec/2019 08:30:39] "GET / HTTP/1.1" 200 17
コードについて
BottleはURLと直後の関数を対応付けるために @route デコレータを使用します。
この場合、 / を myhome() 関数 が処理するようにしています。今回はGETメソッドでリクエストを受け取りましたが、
@route(method='POST') と指定すれば、POSTメソッドによるリクエストを受け取ることができます。
run() 関数により、ウェブサーバを実行します。
このように簡単実装できるためテスト用として役に立つと思われます。
上記のコードでは、コード内でテキストを作成していましたが、
HTMLファイルを作成してそのファイルをブラウザで表示することもできます。
HTMLファイルの埋め込み
まず、bottle2.pyとindex.htmlを同じフォルダ内に用意します。
index.htmlを次のように記述します。
It's my <b>new</b> home page
bottle2.pyを次のように記述します。
from bottle import route, run, static_file
@route('/')
def main():
return static_file('index.html', root='.')
run(host='localhost', port=9999)
それではサーバーを立ち上げます。
$ python bottle2.py
http://localhost:9999にブラウザでアクセスします。

コードについて
static_file() 関数を呼び出すことで、引数の root が示すカレントディレクトリの index.html をレスポンスとして返すことができます。
他にも様々な機能があります。
例えば、
run() の次の引数を追加することもできます。
-
debug=True: HTTPエラーが返されたときにデバックページが作られます。(本場稼働するウェブサーバでは設定してはいけません。) -
reloader=True: Pythonコードに変更を加えたときにブラウザにページが再ロードされる。
また、URLに引数を渡して、渡された値を使うこともできます。以下のコードで実現できます。
@route('/<thing>')
def main(thing):
return f'{thing}'
開発者サイト:https://bottlepy.org/docs/dev/
Flask
FlaskもBottleと同じように簡単に使用できます。
まずはインストール。
pip install flask
では、flask1.pyを用意します。
要件として、
- URL「
/」にアクセスするとindex.htmlファイルがマッピングされるようにしましょう。 - URL「
/sample/some」にアクセスすると、「some」を引数の値としてブラウザに「some」と表示しましょう。 - URL「
/sample1?thing=hello&something=world」にアクセスすると、クエリ文字列で指定した値をflask1.htmlに埋め込んで表示しましょう
ここで、Flaskの静的ファイルのデフォルトディレクトリは static であるため、そのディレクトリのファイルに対するURLも /static で始まります.
from flask import Flask, render_template, request
app = Flask(__name__, static_folder='.', static_url_path='')
# http://localhost:9999/でアクセスされたときに返す内容
@app.route('/')
def myhome():
return app.send_static_file('index.html')
@app.route('/sample/<thing>')
def echo(thing):
return thing
# sample1/以降のクエリ文字列を複数の引数として受け取る
@app.route('/sample1/')
def echo1():
kwargs = {}
kwargs['thing'] = request.args.get('thing')
kwargs['something'] = request.args.get('something')
return render_template('flask1.html', **kwargs)
app.run(host='localhost', port=9999, debug=True)
次にflack1.htmlを作成します。
新しく templates というフォルダを作成します。その配下に以下のコードを保存します。
<html>
<body>
It's my <b>new</b> home page
<br>{{ thing }}
<br>{{ something }}
</body>
</html>
サーバーを起動した後、ブラウザでhttp://localhost:9999/sample1/$thing=hello&something=worldにアクセスすると以下のように表示されます。

Apache
次にApache HTTP Serverを使用して、Pythonのスクリプトを埋め込みましょう。
apacheウェブサーバーで特に優れているWSGIモジュールは mod_wsgi らしいのでこれを使用します。(引用: 入門Python3)
このモジュールはPythonコードをApacheプロセスの中で実行することも、Apacheと通信する別プロセスで実行することもできます。
使用OSがWindows以外であれば、すでにApache入っていますが、Windowsならダウンロードしなければなりません。
私はApache Loungeからhttpd-2.4.41-win64-VS16.zipsをダウンロードしました。
ダウンロードしたファイルにApache24があるのでそれをc:の直下におきましょう(必須ではない)
mod_wsgiを使った方法は2種類あります。
詳しくは https://pypi.org/project/mod-wsgi/
今回はpipを使用してmod_wsgiをインストールします。
$ pip install mod_wsgi
次にPythonスクリプトを記述します。
適当な場所に以下のようにwsgi.pyに記述します。(ちなみに場所はc:/var/www/test/wsgi.py)
import bottle
application = bottle.default_app()
@bottle.route('/')
def home():
return "apache ok"
次に、c:\Apache24\binに移動して
mod_wsgi-express module-configとコマンドを入力します。これによりモジュールの場所を確認できます。この情報は後述するApacheの設定に必要です。
c:\Apache24\bin>mod_wsgi-express module-config
LoadFile "c:/users/appdata/local/programs/python/python37/python37.dll"
LoadModule wsgi_module "c:/users/appdata/local/programs/python/python37/lib/site-packages/mod_wsgi/server/mod_wsgi.cp37-win_amd64.pyd"
WSGIPythonHome "c:/users/appdata/local/programs/python/python37"
次にC:\Apache24\conf\httpd.confのファイル末尾に以下を追記します。
LoadModule wsgi_module "c:/users/appdata/local/programs/python/python37/lib/site-packages/mod_wsgi/server/mod_wsgi.cp37-win_amd64.pyd"
WSGIPythonHome "c:/users/appdata/local/programs/python/python37"
<VirtualHost *:80>
WSGIScriptAlias / c:/var/www/test/wsgi.py
<Directory "c:/var/www/test">
Require all granted
</Directory>
</VirtualHost>
LoadModule、WSGIPythonHomeの記述はmod_wsgi-express module-configの出力を参考に適宜変更してください。
WSGIScriptAliasによって当該のwsgi.pyを探させます。
ここまでできたらapacheを起動します。C:\Apache24\binの作業ディレクトリでhttpd -k startのコマンドで起動します。
ブラウザでhttp://localhost:80にアクセスすると、wsgi.pyで記述した通りにapache okと表示されます。

注意点
application = bottle.default_app()によりWSGI仕様にソースを改良しています。なので、コード内をWSGI仕様にしなければ外部接続ができません。またapplicationをappとかにすると読み込みができません。
mod_wsgiはウェブサーバとPythonコードを結びつけるためにapplication変数を探します。