クラウド開発環境 PaizaCloud IDE (以下PaizaCloudと表記)を使って Hello World シリーズを書いています。今回はPython で CGI を試してみる という回です。Pythonの簡易サーバで HTTP と CGI を体験してみます。
PaizaCloudの具体的な利用方法は以下等を参考にしてください。
https://qiita.com/isy-nishida/items/4e9e49a83952b5eb46dd
クラウド開発環境PaizaCloudクラウドIDEのすすめ
🎯 目的
Webアプリを作ることではなく、
Web がどれだけシンプルな仕組みで動いているかを体験すること。
フレームワークを使うと見えなくなる
“Web の最小単位(HTTP & CGI)” をあえて自分の手で触ってみます。
📝 補足と前提について
本記事では、初学者の方向けに Web の仕組み(HTTP / CGI / フレームワーク)をできるだけシンプルに説明しています。正確さよりも「まず全体像がつかめること」を優先しているため、厳密な仕様や例外は意図的に省略しています。
より正確な技術仕様を調べたい場合は、HTTP RFC や各フレームワークの公式ドキュメントを参照してください。本記事はあくまで 最初の理解の足がかりとして読んでいただければ幸いです。
🌐 まず HTTP とは?(超概要)
HTTP(HyperText Transfer Protocol)は、
TCP/IP の「アプリケーション層」で動くテキスト通信のルール です。
- ブラウザ → サーバへ 文字列でリクエスト
- サーバ → ブラウザへ 文字列でレスポンス
つまり Web は本質的には
テキストの送受信
で動いています。
🌐 CGIとは?(Webの最小実装のひとつ)
CGI(Common Gateway Interface)は、
Webサーバが外部プログラムを実行し、
その標準出力を HTTPレスポンスとして返す仕組み
です。
つまり、
HTTPリクエスト → (CGI) → 標準出力 → HTTPレスポンス
という流れです。
🔍 HTTPリクエストは「環境変数」で渡される
例:
GET /cgi-bin/hello.py?name=nishida HTTP/1.1
CGIでは次のように渡されます:
| HTTPの情報 | CGIプログラムでの受け取り方 |
|---|---|
| GETパラメータ | 環境変数 QUERY_STRING
|
| POSTデータ | 標準入力(stdin) |
| Content-Type | CONTENT_TYPE |
| Content-Length | CONTENT_LENGTH |
Webサーバが “HTTP → OSの入出力” に変換してくれる
というシンプルな構造です。
🔍 CGIプログラム → 「標準出力で HTTPレスポンスを返す」
最も重要なポイントです。
CGIプログラムは:
- まず HTTPレスポンスヘッダ
- 続いて 本文(HTMLなど)
を print するだけ です。
🐍 Pythonで最小のCGI(Hello Web)
ファイル名:hello.py
#!/usr/bin/env python3
import os
print("Content-Type: text/html\n")
query = os.environ.get("QUERY_STRING", "")
print("<html><body>")
print("<h1>Hello Python CGI</h1>")
print(f"<p>QUERY_STRING = {query}</p>")
print("</body></html>")
ポイント:
- 先頭の
Content-Type:が必須 -
QUERY_STRINGで GETパラメータ取得 - あとは print するだけ
📁 ディレクトリ構成
PaizaCloudのデフォルトでの例です。上記プログラムhello.pyを記述して保存します。
/home/ubuntu
├ hello.py
└ cgi-bin/
🛠 Python CGI用にファイルを置く
mv hello.py cgi-bin/hello.py
chmod +x cgi-bin/hello.py
▶ Pythonの簡易サーバを起動する(CGI対応)
起動するのは、cgi-binの上のディレクトリです。
PaizaCloudの例では、/home/ubuntuです。
python3 -m http.server 8080 --cgi
🌍 ブラウザでアクセス(localhostの場合)
http://localhost:8080/cgi-bin/hello.py
※補足ですが、PaizaCloudで実行する場合は、PaizaCloudの地球アイコンであれば、localhostで起動出来ます。そこで表示されたURLを通常のブラウズにコピーして起動すれば外部のブラウザでも起動出来ます。
より詳細が必要な場合は、記事冒頭にも書いた通り、
以下のクラウド開発環境PaizaCloudクラウドIDEのすすめ の投稿を参考にしてください。
https://qiita.com/isy-nishida/items/4e9e49a83952b5eb46dd
GETパラメータつき:
http://localhost:8080/cgi-bin/hello.py?name=myname&lang=python
📌 実行結果(HTML)
ブラウザからからは画面上右クリックで、ページのソースを表示という流れで見えます。
<html><body>
<h1>Hello Python CGI</h1>
<p>QUERY_STRING = name=myname&lang=python</p>
</body></html>
📝【補足】#!/usr/bin/env python3 とは?
CGIプログラムの 1 行目に書く
#!/usr/bin/env python3
これは、このスクリプトを Python3 で実行してください という意味を持つ
“シバン行(shebang)”です。
CGI では Webサーバがスクリプトを 直接実行 するため、この行がないと正しく動かず、
500 Internal Server Error になりやすくなります。
✔ なぜ /usr/bin/env python3 を使うの?
Python3 のインストール場所は、環境によって次のように異なります。
/usr/bin/python3/usr/local/bin/python3- ユーザー環境の
~/.local/bin/python3 - Anaconda などの Python
そこで env を使うことで、
PATH(環境変数)から適切な python3 を自動的に探して実行してくれる
という利点があります。
✔ 一言でまとめると
#!/usr/bin/env python3は
「どの環境でも Python3 を見つけて実行するための最も安全な書き方」
特に CGI では必須。
💡 Webの仕組みが腑に落ちるポイント
| 観点 | Python CGIでの仕組み |
|---|---|
| HTTPレスポンスヘッダ | print("Content-Type: text/html\n") |
| レスポンス本文 | HTMLを print するだけ |
| GETパラメータ | os.environ["QUERY_STRING"] |
| サーバとCGIプログラム | 「環境変数+標準出力」で通信 |
Webは「文字列を返すだけ」で動いている。
これを感じられれば今回のゴールは達成です。
❗ よくあるエラーと対処
✔ 403 Forbidden
chmod +x cgi-bin/hello.py
✔ 500 Internal Server Error
Content-Type の行が抜けている。
✔ 404 Not Found
URLが /cgi-bin/hello.py になっていない。
📝【注意】CGI が動かない原因が「改行コード(CRLF)」の場合
前項のエラーと原因は確認したけど、まだ、なぜか
file not foundNo such file or directory500 Internal Server Error
といったエラーになる場合、
スクリプト自体は存在しているのに動かないことがあります。
その原因の一つが、
改行コードが CRLF(Windows形式)になっていることです。
pythonのWebサーバーの画面(ログ)に表示されるのでなぜかなと思った場合は確認してみてください。
🔍 なぜ改行コードでエラーになるのか?
補足で説明した、CGI スクリプトの先頭の **シバン行(shebang)**ですが。
#!/usr/bin/env python3
この行の末尾が CRLF(\r\n) になっていると、
Linux(Ubuntu) では次のように解釈されてしまいます。
/usr/bin/env python3\r
その結果、
「そんなファイルは存在しない」
と判断され、file not found エラーになります。
つまり、
Python が見つからないのではなく、
改行コードのせいで “別のコマンド名” として扱われている
という状態です。
🛠 対処方法:sed コマンドで改行コード(CRLF)を修正する
sed コマンドを使えば、
1行で CRLF → LF に変換できます。
実行例
sed -i 's/\r$//' post_form.py
複数ファイルまとめて変換する場合
sed -i 's/\r$//' cgi-bin/*.py
🔎 改行コードの確認方法(参考)
改行コードは file コマンドで確認できます。
file post_form.py
CRLF の場合、次のように表示されます。
with CRLF line terminators
✅ 修正後の確認ポイント
- シバン行が正しく解釈される
-
chmod +xが正しく効く - CGI が正常に実行される
📌 ここでの改行コードに関するまとめ(重要)
- CGI スクリプトは 改行コードに非常に敏感
- Windows で作成 → Linux で実行する場合は特に注意
- エラー内容が分かりにくく、原因に気づきにくい
- CRLF 問題は環境依存トラブルの代表例
CGI が動かないときは、
まず「改行コード(CRLF)」を疑うのが実務的なコツです。
🏗️ フレームワークとは? (今後の発展のために補足)
フレームワークとは? そして CGI とどう関係するの?
今回やった CGI は、
- HTTPリクエストを環境変数から読む
- HTTPレスポンスを print で返す
という Webの最小単位でした。
では、普段みんなが使っている Flask、Django、Rails、FastAPI、Laravel などの 「フレームワーク」は何をしているのでしょうか?
✔ フレームワークは “HTTPの面倒なところを全部まとめて管理してくれる仕組み”
フレームワークが内部でやっていることは実はシンプルです。
| 本質的な処理 | CGIでの実装 | フレームワークの内部 |
|---|---|---|
| リクエストの解析 | 環境変数 QUERY_STRING を読む |
ルーターが /?id=1 を自動解析 |
| POSTデータの読み込み | 標準入力(stdin)を読む |
request.form["name"] のように扱える |
| HTTPレスポンス | print("Content-Type: …") |
return jsonify(...) などで返す |
| HTML生成 | print で手書き | テンプレートエンジンで自動生成 |
| ルーティング | 自力でURLを判定 | @app.get("/hello") で自動振り分け |
つまり、
フレームワークは CGI の“面倒を全部ラップした層”
にすぎません。
✔ フレームワークを使っても、結局は「HTTP → プログラム → HTTP」だけで動いている
フレームワークがどれだけ高機能でも、内部では必ずこの流れになっています:
ブラウザ → HTTPリクエスト
↓
(フレームワーク内部)
↓
プログラムの処理(Python/Rustなど)
↓
(フレームワーク内部)
↓
ブラウザへ HTTPレスポンス
つまり、
フレームワークは Web を「楽に書くための道具」であり、
根本的な仕組みは CGI と全く同じ。
ということです。
🔍 なぜ今回 CGI を触る価値があるのか?
- フレームワークを使うと HTTPの仕組みが“隠れる”
- しかし本質は 文字列の入力と出力
- CGI はそれを「生の形」で触らせてくれる
- フレームワークのコードがなぜ動いているかが理解しやすくなる
たとえば FastAPI で:
@app.get("/hello")
def hello(name: str):
return {"message": f"Hello {name}"}
と書けるのは、内部で
- HTTPヘッダの解析
- パラメータの抽出
- JSON変換
- レスポンス作成
を すべて肩代わりしてくれているからです。
✨ まとめ:CGIでWebの本質が見えると、フレームワークも理解しやすい
- Webの基本は「リクエスト(入力)→ レスポンス(出力)」
- CGIはその仕組みを最も“生の形”で触れる
- フレームワークはその上にある便利な層
- 中身の理解があると応用(Python・Rust・Django・FastAPI など)が早くなる
CGIを知る = Webフレームワークの“裏側”を一度見ておくこと
これはエンジニアとして非常に強い経験になります。
🎯 全体のまとめ
- HTTPは TCP/IP のアプリケーション層で動くテキストプロトコル
- CGI = 標準出力で HTTPレスポンスを返す仕組み
- Pythonでも CGI は数行で書ける
- Webの本質を“直接”体験できる
- フレームワークの前に理解すると強い
「Webって、まずはこんなにシンプルなんだ。そしてその上にいろいろな追加仕様が乗っかってきた。」
と実感できればOKです。
次回の以下に続きます。
Python CGI その2 「名前+ひとこと」をPOSTで受け取りファイル操作と検索を試す
https://qiita.com/isy-nishida/items/bbf0fe4a11d7986ea280
今回のCGIから、ファイル操作と検索で簡単なですが、「Webアプリの基礎」を作成してみます。
ありがとうございます。

