Pythonで「CGI(Common Gateway Interface)」を使用する方法を紹介します。
初めてCGIを使う人向けに分かりやすく説明しておりますので、
この機会にPythonがWebサーバ上でどのように動作するのか理解しましょう。
Pythonには強力なWeb開発フレームワークとして、
- Djando
- Flask
- Bottle
があります。 基本となるCGIの動作を学ぶことで上記のフレームワークをより理解し使いこなすことが出来ます。
CGI実行環境
今回使用する実行環境は下になります。
- CentOS 7(KAGOYA VPS)
- Webサーバ:Apache
- Python:Version 3.6.5
作成するファイルと配置先
今回のディレクリ構成は以下になります。
-/cgi-bin
└ pyCGI.py
- /html
└ index.html
Apacheをインストールした時のデフォルト設定になります。
以下、Apacheインストール方法です。
HTMLのフロントページ
今回使用するHTMLのフロントページ「index.html」は以下になります。
<html>
<head>
<meta charset=utf-8>
<title>pyCGI</title>
<head>
<body>
<form action=/cgi-bin/pyCGI.py method=post>
<input type=text name=text>
<input type=submit name=submit>
</form>
</body>
</html>
formタグを使い、「POST」で入力値をCGIに渡します。
PythonのCGIコード
「index.html」から渡された入力値を受け取る「pyCGI.py」は以下になります。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import cgi
import sys
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
print('Content-Type: text/html; charset=UTF-8\n')
html_body = """
<!DOCTYPE html>
<html>
<head>
</haed>
<body>
<h1>Your input is "%s"</h1>
</body>
</html>
"""
form = cgi.FieldStorage()
text = form.getvalue('text', '')
print(html_body % (text))
1行目の「#!/usr/bin/python」で実行するPythonのパスを設定します。
環境ごとに違うので「which python」で確認しましょう。
3行目の「import cgi」でcgiライブラリをインポートします。
9行目の「Content-Type: text/html; charset=UTF-8\n」はCGIを使う上でのおまじないなので、
どのCGIにも記載します。
22,23行目でPOSTされた値を処理して、text変数に格納しています。
CGIファイルに実行権限を付与
「pyCGI.py」をサーバに配置したら実行権限を付けましょう。
chmod 755 pyCGI.py
以下実行ログです。
[root@localhost cgi-bin]# chmod 755 pyCGI.py
[root@localhost cgi-bin]# ls -l
total 4
-rwxr-xr-x. 1 root root 497 Jul 17 20:40 pyCGI.py
実行権限を付与しない場合、以下の500エラーとなるでの注意してください。
エラーログには「Permission denied: exec of \’/xxx/xxx/www/cgi-bin/pyCGI.py\’」と出力されます。
PythonのCGIを実行してみる
「index.html」を格納したURLにアクセスしてみましょう。
表示されたら下のように「Test」と入力してみましょう。
下のように入力した文字列が表示されたら正常に動作しています。
マルチバイト文字列(日本語)がCGIで動作しない場合の対処方法
マルチバイト文字列を「POST」した時に正常に動作しない環境が存在します。
エラーログを確認しますと「UnicodeEncodeError: \’ascii\’ codec can\’t encode characters in position 」が表示されています。
これはCGIの実行ユーザの環境変数に「LANG」が設定されていないため発生します。
この問題の対象方法は、明示的にPythonが出力する文字列を「UTF-8」にすれば解決します。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import cgi
import sys
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
print('Content-Type: text/html; charset=UTF-8\n')
html_body = """
<!DOCTYPE html>
<html>
<head>
</haed>
<body>
<h1>Your input is "%s"</h1>
</body>
</html>
"""
form = cgi.FieldStorage()
text = form.getvalue('text', '')
print(html_body % (text))
4,5行目で「sys」と「io」ライブラリをインポートします。
8行目で標準出力の文字コードを「UTF-8」で出力するように設定することで、
マルチバイト文字列も正常に出力することができます。
下にように表示されれば正常に動作しています。