0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonが動くWebサイトを作ってみた

Last updated at Posted at 2025-02-14

自分は最近,paiza のプログラミング問題に取り組んでいます.
問題に取り組んでいく中で,問題を解く側だけでなく,作る側もやってみたいと考えるようになりました.
そこで,まずは簡単にPythonが動くWebサイトを作ってみました.

この記事では,Pythonが動くWebサイトの作り方を紹介します.
色々な方法があるようですが,今回は GitHub Pages だけで完結させます.
サーバーやクラウドサービスは利用せず,Node等も使いません.
こちらの32行のhtml だけで動きます.こちらのサイトで,実際にPythonを動かせます.
是非,一度試してみてください.

1. Hello World

まずは,Hello Worldを表示します.
最初に用意するhtmlファイルは,以下の通りです.

index1.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>タイトル</title>
</head>
<body>
    <pre>Hello World</pre>
</body>
</html>

preは,整形済みテキストを表し,その中身を等幅フォントで表示します.
最終的にPythonプログラムの出力が表示される部分なので,最初からpreを利用します.
他の解説は,省略します.Web画面の表示は,以下になります.

image.png

次は,JavaScriptでHello Worldを表示させます.

index2.html
~~~略~~~
<body>
-   <pre>Hello World</pre>
+   <pre id="output"></pre>
+   <script type="text/javascript">
+       document.getElementById("output").innerText = "Hello World";
+   </script>
</body>
</html>

元のHello Worldは消して,pre内のテキストを空にします.
代わりに,pre部分にid="output"を設定します.
そして,JavaScriptでid="output"を持つ要素の内部テキストをHello Worldに変更します.
Web画面の表示は,前と同じです.

次は,ボタンをクリックした時にHello Worldを表示します.

index3.html
~~~略~~~
<body>
+   <button onclick="main()">実行</button>
    <pre id="output"></pre>
    <script type="text/javascript">
+       async function main() {
            document.getElementById("output").innerText = "Hello World";
+       }
    </script>
</body>
</html>

実行ボタンをクリックすると,非同期の関数mainが実行されます.
Web画面の表示は,以下になります.

image.png

最後は,Pythonを利用してHello Worldを表示します.

index4.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>タイトル</title>
+   <script src="https://cdn.jsdelivr.net/pyodide/v0.27.2/full/pyodide.js"></script>
</head>
<body>
    <button onclick="main()">実行</button>
    <pre id="output"></pre>
    <script type="text/javascript">
        async function main() {
+           let pyodide = await loadPyodide();
+           let result = pyodide.runPython(`"Hello World"`);
+           document.getElementById("output").innerText = result;
-           document.getElementById("output").innerText = "Hello World";
        }
    </script>
</body>
</html>

WebでPythonを使うため,pyodideを利用します.
上記のように数行記述するだけで,簡単にPythonプログラムが動きます.
Web画面の表示は,前と同じです.

2. Webサイト上で記述したPythonを動かす

htmlファイルにべた書きしたPythonプログラムを動かせました.
次は,Webサイト上で記述したPythonプログラムを動かします.
そのプログラムは,以下になります.

index5.html
~~~略~~~
<body>
    Pythonプログラム<br>
    <textarea id="code" rows="10" cols="79">"Hello World"</textarea><br>
    <button onclick="main()">実行</button>
    <pre id="output"></pre>

    <script type="text/javascript">
        async function main() {
            let code = document.getElementById("code").value;
            let pyodide = await loadPyodide();
            let result = pyodide.runPython(code);
            document.getElementById("output").innerText = result;
        }
    </script>
</body>
</html>

textareaにPythonプログラムを記述します.
"Hello World"は,初期表示です.
記述されたPythonプログラムをdocument.getElementById("code").value;で読み取り,それをpyodide.runPythonで実行します.
以下は,Web画面の例です.

image.png

今回の目的に適した,望ましい動作が実行されていません.
また,エラー処理を書いていないため,エラー時に反応がありません.
そこで,main関数を以下のように変更します.

index6.html
async function main() {
    let code = document.getElementById("code").value;
    let pyodide = await loadPyodide();
-   let result = pyodide.runPython(code);
    
+   let result = "";
+   try {
+       pyodide.setStdout({ batched: (msg) => { result += msg + "\n"; } });
+       pyodide.runPython(code);
+   } catch (error) {
+       result = error
+   }
    document.getElementById("output").innerText = result;
}

Pythonプログラムの標準出力ですが,pyodideの初期設定では,コンソールに出力します.
index6.htmlでは,出力先を変数resultに変更しています.(改行も追加しています)
また,エラー時のメッセージも変数resultに渡すようにしました.
この変更で,Web画面は以下のように変わります.

image.png

標準出力の内容が画面に表示できました.
また,複数行の表示,エラーの表示もできました.

3. 代表的なパッケージのサポート

Pythonが動くWebサイトはできました.
しかし,実はこのままでは,numpyやscipyが動かせません.
そこで,main関数を以下のように変更して,代表的なパッケージをサポートします.

index7.html
async function main() {
    let code = document.getElementById("code").value;
    let pyodide = await loadPyodide();
+   await pyodide.loadPackage(["matplotlib", "numpy", "pandas", "scikit-learn", "scipy"]);

+   document.querySelectorAll("canvas, img.matplotlib").forEach(el => el.remove());
    let result = "";
    try {
        pyodide.setStdout({ batched: (msg) => { result += msg + "\n"; } });
        pyodide.runPython(code);
    } catch (error) {
        result = error
    }
    document.getElementById("output").innerText = result;
}

この変更で,pyodide.loadPackage内に記述したPythonパッケージがサポートされます.
利用可能なパッケージの一覧は,こちらを確認ください.
canvas関連の記述は,matplotlibの実行に対応したものです.
実行ボタンを押した時,既に描画されている画像を消すように設定しています.
これが無いと,画像が消えず,Web画面上に画像が増え続けることになります.

Web画面で,以下のようなプログラムも実行可能になります.

image.png
image.png

普通に実行するより時間がかかりますが,曲線近似,最適化,図の描画ができました.

4. サイト構築

プログラムに対して自由にstyleを適用したり,scriptを追加してください.
この記事では,そこには言及しません.(次の記事で言及します)

完成したファイル群をGithubリポジトリにpushします.
そして,Githubリポジトリにアクセスし,「Settings」⇒「Pages」⇒「Pages」を選択します.
Build and deployment の Sorce で Github Actions を選択し,Github Pages Jekyll の Configure をクリックします.

image.png

後は「Commit changes」ボタンを押すだけでサイト構築は完成です.
https://<ユーザー名>.github.io/<リポジトリ名>/<ファイル名> にアクセスするとWebサイトが見られるはずです.
あるいは,https://github.com/<ユーザー名>/<リポジトリ名>/deployments からアクセスするのが確実です.
ここでデプロイが成功していればURLが表示されます,
失敗の場合,Webサイトが構築できていないので,修正が必要となります.

image.png

終わりに

Pythonが動くWebサイトの作り方を紹介しました.
30行程度でサイトが作れた事に,驚かれた方も多いのではないでしょうか.
見た目や便利な機能に拘らなければ,Webサイト構築は意外と難しくありません.
次回は,このWebサイトの改善に取り組みます.


関連記事・リポジトリ:

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?