HOWTO · Python

HTML で Python を実行する

HTML で Python を実行する方法を学ぶ

このページの内容

静的なHTMLにスクリプトを置いただけでは、ブラウザーでサーバー側のPythonが実行されるわけではありません。Pythonで生成した内容を表示するには、サーバー上でPythonを実行し、その出力をHTTPレスポンスとして返します。小規模な連携ならPHPアプリケーションからPythonプロセスを起動できます。Djangoアプリケーションでは通常、ビューからテンプレートへデータを渡します。

PHPを使ってHTML内でPythonスクリプトを実行する

ページを.phpなどPHPで処理される拡張子で保存し、PHPが設定されたサーバーから配信します。サーバーにはPythonインタープリターも必要で、PHPから起動できる権限が必要です。次の例は、短いPythonスクリプトを作成し、2つの引数を安全に渡して、取得した結果をレスポンスに含める一連の処理を示します。

<?php
$pythonScript = <<<'PY'
import sys

name = sys.argv[1]
count = int(sys.argv[2])
print(f"Hello, {name}! Count: {count}")
PY;

$scriptPath = tempnam(sys_get_temp_dir(), 'page-python-');
file_put_contents($scriptPath, $pythonScript);
$command = 'python3 ' . escapeshellarg($scriptPath)
    . ' ' . escapeshellarg('Mina')
    . ' ' . escapeshellarg('3');
$result = shell_exec($command);
unlink($scriptPath);

?><!doctype html>
<html lang="en">
  <body>
    <p><?= htmlspecialchars($result ?? '', ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?></p>
  </body>
</html>

ここではPHPがpython3を起動し、PythonプロセスはMinaと3をそれぞれsys.argv[1]とsys.argv[2]として受け取ります。shell_exec()がプロセスの出力を取得し、htmlspecialchars()がページに挿入する前にHTML用にエンコードします。この出力はブラウザーに送られるレスポンスの内容であり、サーバーのコンソールに表示されるテキストではありません。

shell_exec()が使えるかどうかはPHPホストの設定によります。また、Webサーバーの実行アカウントにインタープリターを起動する権限が必要です。この例では固定の引数を使っています。動的な値を渡す場合は検証し、各引数を個別にescapeshellarg()でエスケープしてください。信頼できない入力をシェルコマンドに連結してはいけません。規模の大きいアプリケーションでは、リクエストごとにプロセスを起動するより、ジョブキューや専用サービスのほうが適している場合があります。

Djangoを使ってHTML内でPythonスクリプトを実行する

Djangoアプリケーションでは、アプリケーションの処理をPythonのビューに記述し、その結果をテンプレートに渡します。テンプレートはサーバー上で値をHTMLに描画します。ブラウザーが受け取るのは描画済みのページであり、Pythonを実行することはありません。たとえば、ビューでcontext = {"message": "Hello from Django"}を用意してrender(request, "page.html", context)を返し、テンプレートでは{{ message }}を使って値を表示できます。

テンプレート内で再利用可能な表示処理を行うには、カスタムテンプレートタグが便利です。coreという名前のインストール済みアプリで、core/templatetags/__init__.pyとcore/templatetags/my_custom_tags.pyを作成します。後者ではdjangoからtemplateをインポートし、register = template.Library()を設定して、たとえばdef greeting(): return "Hello from Django"のような関数を@register.simple_tagでデコレートします。Djangoがtemplatetagsパッケージを認識できるよう、追加後は開発サーバーを再起動してください。

テンプレートで{% load my_custom_tags %}を使ってモジュールを読み込み、{% greeting %}でタグを呼び出します。このタグはサーバー側のテンプレート描画用にテキストを返すもので、ブラウザーのHTML内で任意のPythonを実行するものではありません。単純な値なら、カスタムタグよりビューとテンプレートコンテキストを使うほうが通常は分かりやすくなります。Djangoにはdate、linebreaks、safe、randomなどの組み込みフィルターもあります。詳しくはDjangoの組み込みテンプレートフィルターのリファレンスを参照してください。

ページの読み込み後にデータが必要な場合は、Djangoのビューをエンドポイントとして公開し、fetch()や別のAJAXクライアントからリクエストできます。機密データを返したり操作を実行したりする前に、認証と認可を確認してください。状態を変更するPOSTリクエストでは、DjangoのCSRF保護を利用し、CSRFトークンを送信します。エンドポイントをPOSTのみに制限しても、それだけで安全になるわけではありません。詳しくはDjangoのCSRFドキュメントを参照してください。

PHPでホストされているサイトに小規模な既存Pythonスクリプトを組み込み、ホストが実行を許可している場合は、PHPからプロセスを起動する方法が適しています。Djangoアプリケーションでページのデータを計算して描画するには、通常ビューとテンプレートを使います。テンプレート内で表示処理を再利用する場合はカスタムタグを、ページ読み込み後に取得するデータにはエンドポイントを使います。