10

Currently I and many others are using a Python HTTP server on several platforms (Windows, OS X and potentially Linux). We are using a Python HTTP server to test a JavaScript game.

Right now we are launching the Python HTTP server through the command line on each platform (CMD, Terminal, etc.). Although this works well, it is becoming a pain to use this method, it would be nice to have a simple script that starts the Python HTTP server up.

The script needs to work on all platforms, seeing as all platforms will have Python installed it makes sense to write the script in Python.

Currently we are using the following commands to start the server:

On python 3

python -m http.server

On python 2

python -m SimpleHTTPServer

How would I put one of these lines into Python code, which I could save as a .py and simply double click on to start the HTTP server?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
ducsuus
  • 145
  • 1
  • 1
  • 11

5 Answers5

11

The accepted answer is not work for me. If it's not working for you too, please try this.

from http.server import HTTPServer, SimpleHTTPRequestHandler

httpd = HTTPServer(('localhost', 8000), SimpleHTTPRequestHandler)
httpd.serve_forever()
Trieu Nguyen
  • 933
  • 1
  • 11
  • 17
  • OP asked to have script that auto detect Python and fire specific module. Your answer works only with python 3+ thus I downvoted. Python 2.7: `Import Error, no module named http.server` – Pawel Cioch Mar 15 '22 at 04:58
10

The following script would do the same for either Python 2 or 3:

try:
    # Python 2
    from SimpleHTTPServer import test, SimpleHTTPRequestHandler
except ImportError:
    # Python 3
    from http.server import test, SimpleHTTPRequestHandler

test(SimpleHTTPRequestHandler)

This runs the exact same callable that is used when you run the module from the command line with the -m switch.

The Python 3 version includes command-line support to determine what interface and port to bind to, but your command line doesn't make use of this anyway.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • I receive a 501 in the browser when I serve with http.server.test() in Python 3.7.4. Simplest way I am able to do this in code (i.e. not just -m http.server from command line) is with HTTPServer as Trieu describes below. – michael Oct 27 '19 at 23:16
  • @michael ah, thanks for the heads-up! Looks like I missed that Python 3 switched out the default used for the handler argument. I corrected the answer now. – Martijn Pieters Oct 28 '19 at 00:18
0

To give a more general answer, you can call any external command via the subprocess module:

from platform import python_version
from subprocess import call
if (int(python_version()[0]) < 3) :
    call(["python", "-m", "SimpleHTTPServer"])
else :
    call(["python", "-m", "http.server"])
bcoka
  • 84
  • 7
  • OK, I will keep this in mind in the future. Does this allow for any console command to be called, or only a set range of Python modules to be called (if so, where can I find a list?). – ducsuus Jul 04 '14 at 21:20
  • It is equivalent to typing the string literal in your system's terminal. `subprocess` replaces old modules, (e.g. `os`). A variation of `call` is explained here: http://stackoverflow.com/a/7681815/3799591 For running a basic HTTP server, `call` is better than `Popen` (Ctrl-C stops the server). Installing multiple versions of Python allows running "python3 script.py" and calling "python -m http.server", which breaks ("python" usually defaults to 2), but as long as you source with "python", you're fine. In that sense, the accepted answer is better. I took the question from a shell scripting POV. – bcoka Jul 04 '14 at 22:38
  • 1
    You are spawning a subprocess **from** a Python script to execute a **Python** module? Seriously? – Lukas Graf Jul 04 '14 at 22:38
  • Well, when you look at it _that_ way... :-P In part, the question asks about running terminal commands from a .py file, and I thought it would be beneficial to mention how that's done. – bcoka Jul 04 '14 at 22:46
  • This one is kind of not optimized, but it works for me. the accepted answer did not. it give me 502, not support [GET] – Trieu Nguyen Jan 29 '19 at 04:25
0

create a file server.py with this content:

import sys
port=sys.argv[1]

if sys.version_info < (3, 0):
    from SimpleHTTPServer import SimpleHTTPRequestHandler
    from BaseHTTPServer import HTTPServer
else:
    from http.server import HTTPServer, SimpleHTTPRequestHandler

httpd = HTTPServer(("127.0.0.1", int(port)), SimpleHTTPRequestHandler)
print("Serving HTTP on localhost port " + port + " (http://localhost:" + port + "/) ...")
httpd.serve_forever()

Usage:

python server.py 8887

Pawel Cioch
  • 2,895
  • 1
  • 30
  • 29
0
simplified version of the code that also extract values from url:

from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qs

class MyHandler(BaseHTTPRequestHandler):
        def do_GET(self):
        url_parts = urlparse(self.path)
        query_params = parse_qs(url_parts.query)
        param1 = query_params.get('param1', [''])[0]
        param2 = query_params.get('param2', [''])[0]
        print(f"param1: {param1}")
        print(f"param2: {param2}")
        self.server.shutdown()

def run_server():
    server_address = ('', 8000)
    httpd = HTTPServer(server_address, MyHandler)
    httpd.serve_forever()

run_server()