Drew
Drew

Reputation: 1014

How do you execute a server-side python script using http.server?

I have a collection of python scripts, that I would like to be able to execute with a button press, from a web browser.

Currently, I run python -m http.server 8000 to start a server on port 8000. It serves up html pages well, but that's about all it does. Is it possible to have it execute a python script (via ajax) and return the output, instead of just returning the full text of the .py file.

Additionally, if not, is there a simple (as in only 1 or 2 files) way to make this work? I'm looking for the equivalent of PHP -s, but for python.

For completeness, this is my html

<h1>Hello World</h1>

<button>
Click me!
</button>

<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.js">    </script>

<script>
  $('button').click(function(){
    $.get('/gui/run_bash.py');
  });
</script>

Upvotes: 4

Views: 18787

Answers (2)

Robᵩ
Robᵩ

Reputation: 168886

Add --cgi to your command line.

python -m http.server --cgi 8000

Then place your python scripts in ./cgi-bin and mark them as executable.

$ mkdir cgi-bin
$ cp hello.py cgi-bin/hello.py
$ chmod +x cgi-bin/hello.py

You may need to slightly modify your python scripts to support the CGI protocol.

Here is the server running:

$ cat cgi-bin/hello.py 
#! /usr/bin/env python3

print("Content-Type: application/json")
print()

print('{"hello": "world"}')
radams@wombat:/tmp/z/h$ python -m http.server --cgi
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
127.0.0.1 - - [20/Mar/2018 18:04:16] "GET /cgi-bin/hello.py HTTP/1.1" 200 -

Reference: https://docs.python.org/3/library/http.server.html#http.server.CGIHTTPRequestHandler

Upvotes: 5

sytech
sytech

Reputation: 41219

http.server merely serves static files, it does not do any serverside processing or execute any code when you hit a python file. If you want to run some python code, you'll have to write an application to do that. Flask is a Python web framework that is probably well-suited to this task.

Your flask application might look something like this for executing scripts...

import subprocess
from flask import Flask
app = Flask(__name__)

SCRIPTS_ROOT = '/path/to/script_dir' 
@app.route('/run/<script_name>')
def run_script(script_name):
    fp = os.path.join(SCRIPTS_ROOT, script_name)
    try:
        output = subprocess.check_output(['python', fp])
    except subprocess.CalledProcessError as call:
        output = call.output # if exit code was non-zero
    return output.encode('utf-8') # or your system encoding

if __name__ == '__main__':
    app.run(host='127.0.0.1', port=8000)

And of course, I should include an obligatory warning 'having a webserver execute commands like this is insecure', etc, etc. Check out the Flask quickstart for more details.

Upvotes: 4

Related Questions