0

I want to be able to call a python script by making a request on a Python server I created from this tutorial

I want that when the server receive a particular request, it launch the Python script.

I tried this simple code without success. I thought that on GET request it will launch the externalFunc.py script. But it does not.

#!/usr/bin/env python

from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import os

#Create custom HTTPRequestHandler class
class KodeFunHTTPRequestHandler(BaseHTTPRequestHandler):

#handle GET command
def do_GET(self):
    execfile("root\externalFunc.py")



def run():
   print('http server is starting...')

#ip and port of servr
#by default http server port is 80
server_address = ('127.0.0.1', 80)
httpd = HTTPServer(server_address, KodeFunHTTPRequestHandler)
print('http server is running...')
httpd.serve_forever()

if __name__ == '__main__':
run()

I dont have any error, just nothing happens. What am I doing wrong ?

EDIT : Here is the GET request made by the client :

import sys

#get http server ip
http_server = '127.0.0.1'
#create a connection
conn = httplib.HTTPConnection(http_server)

#request command to server
conn.request('GET', '','')

#get response from server
rsp = conn.getresponse()

#print server response and data
print(rsp.status, rsp.reason)
data_received = rsp.read()
print(data_received)

conn.close()

And I got a 501 error from the server :

127.0.0.1 - - [20/Jan/2018 15:46:46] code 501, message Unsupported method ('GET')
127.0.0.1 - - [20/Jan/2018 15:46:46] "GET / HTTP/1.1" 501 -
3
  • Without seeing root\externalFunc.py there is now way to know. The do_GET handler must send an answer to the request. I don't think root\externalFunc.py does that for you. Why do you use execfile anyway? Commented Jan 19, 2018 at 15:23
  • You are right, maybe i don't use the good functions. What I want to do is simple : I want to launch a Python script on any request, wether it's GET / POST / Whatever.. Commented Jan 19, 2018 at 17:26
  • did you try in web browser http://127.0.0.1:80 ? Commented Jan 19, 2018 at 19:45

1 Answer 1

1

First of all, the python code you've posted is broken, if you did copy&paste from your own script, then your code is invalid python because the indentation is wrong.

Secondly, it's a bad idea to just execute a script with exec, this can be dangerous, specially if you are not the owner of the script and how knows what the script does.

So let's modify your root/externalFunc.py first: let's add a run method that does the work of the script. Instead of just printing to the standard output, the run function should return something, for example the a string or a dictionary containing the results.

Because you haven't shown us the code of root/externalFunc.py, I assume that the script may look like this:

#!/usr/bin/env python
# root/externalFunc.py
# old version

def run():
    # ... doing some work,
    # result is a variable with the result
    print "Result: %d" % result

if __name__ == '__main__':
    main()

Now let's modify it.

  1. create an empty file __init__.py in the root/ directory:

    // on linux/mac/bsd
    $ touch root/__init__.py
    
    // on windows
    cmd> type NUL > root/__init__.py
    

This allows to use from root.whatever export something in another module.

  1. Let's add a run method that actually does the work:

The new version:

#!/usr/bin/env python
# root/externalFunc.py
# new version

import sys

def run(parm1, param2, param3):
    # ... doing some work,
    # result is a variable with the result

    return = {
        "success": True,
        "value": result
    }

def main():
    if len(sys.argv) != 4:
        print >> sys.stderr, "usage: %s param1 param2 param3" % sys.argv
        return 1
    param1 = int(sys.argv[1])
    param2 = sys.argv[2]
    param3 = int(sys.argv[3])

    res = run(param1, param2, param3)
    if res["success"]:
        print "Result: %d" % res["value"]
        return 0
    else:
        print "Error, ..."
        return 1

if __name__ == '__main__':
    return main()

Now we have to change your server code to import the run method and use that method instead of using exec or execfile

from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from root.externalFunc import run as externalFunc_run

class KodeFunHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        param1 = 3
        param2 = "max"
        param3 = -12

        res = externalFunc_run(param1, param2, param3)

        if res["success"]:
            answer = "The result is: %d" % res["value"]
        else:
            answer = "Error while computing externalFunc"

        #send code 200 response
        self.send_response(200)

        #send header first
        self.send_header('Content-type','text/plain')
        self.end_headers()

        # send answer
        self.wfile.write(answer)

Now if you don't want (or cannot) change the code of root/externalFunc.py, or the script is not a python script, then you could use subprocess.check_output.

import subprocess
import shlex

# bad, don't do that
# exec("root/externalFunc.py")

# do this instead
answer = subprocess.check_output(shlex.split("root/externalFunc.py params..."))
print "Answer: %s" % answer

Using subprocess.check_output is much more safe, behind the scenes it calls subprocess.Popen, which executes a child program in a new process, thus the child program won't cause damage if it goes bersek.

Now you can replace this line res = externalFunc_run(param1, param2, param3) with the subprocess.check_output line.

Sign up to request clarification or add additional context in comments.

10 Comments

Really thanks for your help and your time, I really appreciate it. Alright I see how it could works now. I still have one problem : When I try to send a Get request from a client script, I receive an error Unsupported method ('GET') error 501. Why is that ?
@thib I don't know, I don't use BaseHTTPRequestHandler, I usually use tornado. I'll take a closer look later. The error message is probably an exception, at which part of the code did you get that?
Many thanks. I got it when posting my GET request : http_server = '127.0.0.1' #create a connection conn = httplib.HTTPConnection(http_server) #request command to server conn.request('GET', '','') #get response from server rsp = conn.getresponse()
@thib is this on the server script or the client script?
This is the request made by the client, on the server I didnt changed the do_GET method you wrote.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.