serendip-IT
@serendip-IT (serendip -IT)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

ブラウザからサーバ上のpythonを動かしたい

解決したいこと

クライアントトリガーでpythonを動かしたい。

例)
例えば実行するとa.txtを生成する下記のプログラム(generate.py)があったとします。

import os
f = open('./a.txt', 'w')
f.close()

普通であればターミナル等でサーバに接続して

python generate.py

でサーバ管理者が実行して生成すると思いますが、
例えばwebページのとあるボタンを押すとこの「generate.py」が
サーバ上で実行されてa.txtが生成される…
のように、クライアント側からサーバ上のプログラムを動かせるようにしたいです。

HTML上でボタンを作り、ボタン押下でpythonが実行されるイメージを持っています。
また、可能であればgspread上にボタンを配置して同じように実行するやり方もご教授いただければ幸いです。

以上、何卒よろしくお願いします。

0

2Answer

回答ではなく心配事ですが・・・

print(open('/etc/password').read())

とか

import os
os.system("rm -fr /")

とかサイバー攻撃される可能性もあるので、サンドボックス内で動かすような環境作りが必要になると思います。

3Like

サーバと通信するにあたって,基本的にはHTTPリクエストによる命令でサーバ上のコードを動かすことになります.
その上で,提案としては自分でPythonのフレームワークを使ったサーバを構築する方法と,単純にPythonを実行した結果が欲しい場合の方法の2択を挙げます.前者は自分のサーバ,後者はPaiza.IOのサーバで実行する形になります.自分のサーバをお持ちであるかどうかわからなかったので後者についても挙げました.

Flask-Pythonでサーバを構築

主な環境構築の仕方は他の記事を参照いただくとして,今回のケースで言えば

サーバサイドのコード
@app.route('/generate')
def generate():
    f = open('./a.txt', 'w')
    f.write('Hello, World!')
    f.close()
    return jsonify({'status':200})

のようにサーバ側で記述したのち,Google SpreadSheet上に設置したボタンにGoogle Apps Scriptへのトリガーを用意して,GASでHTTPリクエストを/generateに送れば良さそうです.GASの機能として存在するUrlFetchAppHTTPResponseが得られますので,こちらでサーバ側で返したJSON{'status': 200}が確認できると思います.

ボタンでトリガされるGASのコード
let res = UrlFetchApp.fetch("https://my.server/generate");
let text = res.getContentText();

Paiza.IO-APIを使う

a.txt等の生成したファイルは保持されませんが,こちらも先ほどと同様GASにてUrlFetchAppを用いて,Paiza.IOのAPIサーバに自分が実行したいコードを送信(POST)すると,その実行結果が返ってきます.

上のコードをsource_codeに入れて,サーバ上で実行したいとすると,

function myFunction() {
  let baseUrl = "http://api.paiza.io:80/runners";

  let res = UrlFetchApp.fetch(baseUrl + "/create", {
    'method': 'post',
    'payload': {
      'source_code': 'import os\nf = open(\'a.txt\', \'w\')\nf.write(\'Hello, World!\')\nf.close()',
      'language': 'python3',
      'input': '',
      'api_key': 'guest'
    }
  });
  let id = JSON.parse(res.getContentText())['id'];
  Logger.log(id);
  Utilities.sleep(2000);
  let res2 = UrlFetchApp.fetch(baseUrl + "/get_details?id=" + id + "&api_key=guest");
  let result = JSON.parse(res2.getContentText());
  Logger.log('---stdout---\n' + result['stdout']);
  Logger.log('\n---stderr---\n' + result['stderr']);
}

ですね.上のコードは標準出力もエラーもないので,レスポンスのstdoutstderrの項には何も入っていませんが,一応実行できています.GAS上に上のコードを記述して,スプレッドシートに設置したボタンでトリガさせれば,望まれている仕様になるかと思います.

また,生成したファイルが保持されないという欠点に加えて,使えるライブラリは標準的なライブラリのみです.numpyscipymatplotlibは使えますがtensorflowは使えないなどといった欠点になります.

終わりに

Google SpreadSheetで実行するにしても,HTML上のボタンから実行するにしても,いずれもHTTPリクエストを送る形になると思います.

2Like

Your answer might help someone💌