JavaScript
前回、JavaScriptのdocument.write、innerHTML、outerHTML、textContentの違いを解説しました。
今回はそろそろやりたかった本命の事。
JavaScriptからPythonのプログラムを実行するということに手をつけてみます。
PythonでWebアプリを作ろうとすると、DjangoやFlaskのようなフレームワークを使って、PythonでWebサイト丸ごと立ち上げたり、WordPressと共存させるということをせねばいけませせん。
それをやったとしても今、このWordPressで作成したブログに「埋め込む」ということはできません。
WordPressを使いつつ、Webアプリを作っていきたいと思っていたので、WordPressでユーザーの入力した情報を取得しつつ、処理するということをやりたいのです。
そしてずっとPythonを触ってきたので、できる事なら処理のメインはPythonでやりたい。
ということで目指してきたのが、JavaScriptを使ってユーザーの入力を取得し、それをPythonに渡すということでした。
Pythonを学んでいる人にとっては、同じことをやりたい人も多いと思うので、参考になれば幸いです。
ちなみに今回のプログラムはローカルでは動かず、サーバーにアップして実行する必要がありましたので、ご注意ください。
それでは始めていきましょう。
JQueryとAjax
調べていくとJavaScriptからPythonを実行するには、単純にコマンドを実行させればいいと言うわけではないらしい。
(PHPはコマンドを実行するコマンドがあるらしいです)
そしてJavaScriptのライブラリの一つである「jQuery(ジェイクエリー)」というものの「Ajax(エイジャックス)」を使うようです。
jQueryとは、Webブラウザ用のJavaScriptのプログラムを簡単に書けるように設計されたJavaScriptのライブラリだそうです。
そしてAjaxとは「Asynchronous JavaScript + XML」の略」で非同期的にWebブラウザとサーバーの通信を行う方法だそうです。
正直、よく分かりませんが、これでJavaScriptからPythonを実行できるということなので試していきましょう。
まずはjQueryを準備しなければいけませんが、これはサーバーにJQueryをインストールする方法とCDN(コンテンツデリバリーネットワーク)を使う方法があるようです。
CDNの場合は、HTMLにURLを記載し、そのHTMLが読み込まれた際に、そのライブラリを読み込むという仕組みらしいです。
jQueryではCDNを使う方法が一般的なようなので、とりあえずCDNの方法を選択しました。
まずjQueryのサイト(https://jquery.com)に行きます。
「Download」をクリック。
ページの下の方へ行き、「jQuery’s CDN provided by StackPath」を探します。
「https://code.jquery.com」をクリックします。
また「Google CDN」や「Microsoft CDN」などでも同じライブラリが配信されるということなので、そちらでもOKです。
「jQuery 3.x」の「jQuery Core 3.6.3」の「minified」をクリックします。
バージョンは変わりますので、適宜読み替えてください。
また「uncompressed」と「minified」の違いはファイルサイズが最小化されているかどうかだけで機能に違いはないとのことです。
「slim」とか「slim minified」は機能を最小限に絞っているらしいので、「minified」を選んでおくのがいいようです。
コードが出てきますので、これをコピー(右の青のボタンでできます)して、HTMLのhead内にペーストします。
ということでこんな感じ。
<!DOCTYPE html>
<html lang="ja">
<head>
<script src="https://code.jquery.com/jquery-3.6.3.min.js" integrity="sha256-pvPw+upLPUjgMXY0G+8O0xUf+/Im1MZjXxxgOcBQBXU=" crossorigin="anonymous"></script>
<meta charset="UTF-8">
</head>
<body>
<script>
</script>
</body>
</html>
これでこのHTMLが実行されると、jQueryが読み込まれます。
jQueryが正常に動くか、またAjaxを動かすことができるかはこちらのプログラムをサーバー上で実行すると分かります。
<!DOCTYPE html>
<html lang="ja">
<head>
<script src="https://code.jquery.com/jquery-3.6.3.min.js" integrity="sha256-pvPw+upLPUjgMXY0G+8O0xUf+/Im1MZjXxxgOcBQBXU=" crossorigin="anonymous"></script>
<meta charset="UTF-8">
</head>
<body>
<script>
$.ajax({
}).done(function(response){
alert("OK");
}).fail(function(){
alert("failed");
});
</script>
</body>
</html>
「$.ajax()」がAjaxを使う部分のプログラムを示していて、「done」が通信が成功した場合の関数、「fail」が通信が失敗した場合の関数です。
これでサーバーにアップし、アクセスしてみて、「OK」と表示されたら、Ajaxが使える状態になっています。
ちなみにローカルで実行してみたところ、「failed」がでて通信に失敗していることが分かります。
なぜローカルだと失敗するのかよく分かりませんが、こういうものらしいです。
ここで「Ajaxが使える状態」と書きましたが、ここからPythonが実行できるまでが長かった。。。
ということで順をおってPythonが実行できる状態になるまで解説していきます。
AjaxからPythonが実行できるようになるまで
次にAjaxからPythonが使えるようにしていきます。
ただし私が使用しているサーバーではすでにPythonをインストールし、Cronで実行できるようになっています。
ただしこの状態ではAjaxからPythonを実行することはできませんでした。
必要だったのはこちらの作業。
- .htaccessの編集
- PythonプログラムにPythonのパスの記載
- ファイル名の変更
- パーミッションの変更
- Pythonプログラムの出力に出力形式を記載
それでは順に見ていきましょう。
.htaccessの編集
まず最初にぶち当たった壁が、PythonプログラムがPythonプログラムとして認識されず、単に文字列として認識されてしまう問題でした。
どういうことかというとこんなプログラムを作成してみました。
<!DOCTYPE html>
<html lang="ja">
<head>
<script src="https://code.jquery.com/jquery-3.6.3.min.js" integrity="sha256-pvPw+upLPUjgMXY0G+8O0xUf+/Im1MZjXxxgOcBQBXU=" crossorigin="anonymous"></script>
<meta charset="UTF-8">
</head>
<body>
<div id="text"></div>
<script>
let text = document.getElementById("text");
$(function(){
$.ajax({
url: 'test.py',
type: 'post',
data: 'success'
}).done(function(data){
text.innerHTML = data;
}).fail(function(){
alert('failed');
});
});
</script>
</body>
</html>
HTMLでは、このHTMLが実行されたらAjaxで「test.py」を実行しにいきます。
その際、「success」という文字列も送ります。
$.ajax({
url: 'test.py',
type: 'post',
data: 'success'
})
そしてPythonで処理された結果をテキストに表示します。
.done(function(data){
text.innerHTML = data;
})
また通信に失敗した場合はアラートウインドウで「faild」と表示されます。
.fail(function(){
alert('failed');
});
Pythonのプログラムはsys.stdin.readline()で標準入力を受け取り、それに「OK」を追加し、print関数で出力します。
このprint関数で出力された部分が、JavaScriptの「.done」の関数で受け取られます。
import sys
recieve = sys.stdin.readline()
recieve = recieve + "OK!"
print(recieve)
これを実行したところ、こんな画面が表示されました。
Pythonプログラムがそのまま文字列として表示されてしまったわけです。
これを解消するには、サーバーの「.htaccess」にこちらのコマンドを追加します。
AddHandler cgi-script .py
これで再度HTMLにアクセスします。
先ほどのようにPythonプログラムが文字列として処理されなくなりましたが、通信に失敗してしまいました。
ここでコンソールの確認をしてみます。
Safariならブラウザ上で右クリック > ページのソースの表示 > コンソール で表示できます。
それがこちら。
「status of 500」が返ってきています。
これはサーバー側で何かエラーが起こったよという返事とのことです。
先ほどの流れからいうと、Ajaxだけなら通信可能で、Pythonプログラムにつなげた際にエラーとなっているので、Pythonプログラムに何らかの間違いがあったのだと推測されます。
ここでまず必要なのはサーバー上のPythonのパスをPythonプログラム内に記載することでした。
PythonプログラムにPythonのパスを記載
ということでまずはサーバー上のPythonのパスを確認します。
サーバーにSSHで接続し、「which python3」を実行します。
XserverへのSSH接続に関してはこちらの記事で解説していますので、よかったらどうぞ。
ちなみに私はXserverにLinuxbrewでPython3をインストールしています。
サーバーやPythonのインストールの仕方によっては、Pythonのプログラム名(which pythonかwhich python3か)やPythonの場所が違うと思いますので注意してください。
私の設定ではこれで「~/.linuxbrew/bin/python3」というパスが取得できました。
これをPythonプログラムに記載しますが、このまま記載してもPythonは動きません。
パスの最初の「~」は省略されている部分なので、保管してやる必要がありました。
ということでPythonプログラムに追加するパスは「/home/アカウントID/.linuxbrew/bin/python3」です。
これに「#!」をつけてPythonプログラムの最初の行に追加します。
#!/home/アカウントID/.linuxbrew/bin/python3
import sys
recieve = sys.stdin.readline()
recieve = recieve + "OK!"
print('Content-type: text/html\n')
print(recieve)
ファイル名の変更
PythonプログラムにPythonのパスを記載してもサーバーエラー500は解消しませんでした。
次にこれは後から分かったことなのですが、Pythonのファイル名が「test.py」だと何か競合するプログラムがあるのか、うまく動かないようでした。
ということでファイル名をtest.pyから「recieve.py」に変更しました。
それに伴い、HTML(jQuery)で呼び出すプログラム名も変更しています。
<!DOCTYPE html>
<html lang="ja">
<head>
<script src="https://code.jquery.com/jquery-3.6.3.min.js" integrity="sha256-pvPw+upLPUjgMXY0G+8O0xUf+/Im1MZjXxxgOcBQBXU=" crossorigin="anonymous"></script>
<meta charset="UTF-8">
</head>
<body>
<div id="text"></div>
<script>
let text = document.getElementById("text");
$(function(){
$.ajax({
url: 'recieve.py',
type: 'post',
data: 'success'
}).done(function(data){
text.innerHTML = data;
}).fail(function(){
alert('failed');
});
});
</script>
</body>
</html>
パーミッションの変更
次にPythonプログラムのパーミッションの変更を行いました。
パーミッションとはそのファイルに対して、誰がどんなこと(読み込んだり、書き込んだり、実行したり)ができるかの権限のことです。
私の環境ではアップロードしたファイルは「604」となっており、所有者は「読み取りと書き込み」が可能、グループのユーザーは何もできない、その他の人は「読み取り」が可能となっています。
今回、Ajaxでアクセスして実行したいため、外部の人でも実行できるように設定する必要がありました。
そこで所有者は「読み取り、書き込み、実行」ができるように「7」に、他のユーザーは「読み取りと実行」が可能なように「5」に設定しました。
ということで「755」に変更しました。
Pythonプログラムの出力に出力形式を記載
AjaxでPythonプログラムの出力をJavaScriptが受け取るためには、最初の出力にその出力形式を記載する必要があるとのことでした。
ということで「print(‘Content-type: text/html\n’)」を出力の最初に追加しました。
#!/home/アカウントID/.linuxbrew/bin/python3
import sys
recieve = sys.stdin.readline()
recieve = recieve + "OK!"
print('Content-type: text/html\n')
print(recieve)
これでようやく「successOK!」の表示が出て、JavaScriptからPythonを実行でき、そしてPythonの出力をJavaScriptで取得できました。
ちなみにPythonプログラムのエンコーディングを2行目に書くのも必要だというのもありましたが、私の環境では必要ありませんでした。
# -*- coding: utf-8 -*-
何はともあれこれでJavaScriptからPythonを実行できるようになったので、Webアプリの幅が広がりそうです。
次回はHTMLのチェックボックスを設置し、JavaScriptでその状態を取得する方法を解説します。
ではでは今回はこんな感じで。
コメント