29

I am using Windows 7 and Python 3.4.3. I would like to run this simple helloworld.py file in my browser:

print('Content-Type: text/html')
print( '<html>')
print( '<head></head>')
print( '<body>')
print( '<h2>Hello World</h2>')
print( '</body></html>')

What I do is:

1) Go to command line C:\Python (where python is installed)

2) run: python -m http.server

3) Got to Firefox and type http://localhost:8000/hello.py

However, instead of "Hello World", the browser just prints the content of the hello.py file.

How can I fix it?

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
Yura
  • 2,381
  • 8
  • 33
  • 44
  • 1
    your webserver isnt "running python". your python is running a webserver. – TehTris May 28 '15 at 20:29
  • You should edit your original question instead of just reposting it. – kylieCatt May 28 '15 at 20:29
  • after re-reading my comment it seemed kinda sarcastic, so let me explain a little more. visit https://bootstrap.pypa.io/get-pip.py and watch how the file contents are just displayed in your browser. Your webserver is not configured to actually do anything with python commands, its just serving whatever files you have in the directory as the most basic of all no frills webserver. – TehTris May 28 '15 at 20:33
  • 1
    @IanAuld, my other question was regarding configuring WAMP. This question is regarding http.server. No reposting - this is a different question – Yura May 28 '15 at 20:33
  • Once again I will point you to [Flask](http://flask.pocoo.org/) and [Bottle](http://bottlepy.org/docs/dev/index.html) – kylieCatt May 28 '15 at 20:35
  • @TehTris, I clicked the link and it has downloaded a .py file. Nothing was displayed in my browser. what should I do with it? – Yura May 28 '15 at 20:40
  • @IanAuld, I tried to read it the last time, but it seems Chinese to me, I dont really know where to start and what to do with that. If you want to prompt me to a more precise to read, Id love your help. – Yura May 28 '15 at 20:42
  • @IanAuld depending on what you are doing it is enough to use the python built-in functions. tho' of course you are right that flask and other (micro-)frameworks can help a lot, – Tom-Oliver Heidel May 28 '15 at 20:43
  • If the OP is a beginner (which I'm assuming they are) dealing with server configs and rendering out different pages, routing and security concerns can quickly become overwhelming. Letting a framework do the heavy lifting while they learn will probably be much easier in the long run. – kylieCatt May 28 '15 at 21:02
  • 1
    @Yura This [tutorial](http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world) will cover a lot of things but is pretty easy to follow along with. This [one](http://code.tutsplus.com/tutorials/an-introduction-to-pythons-flask-framework--net-28822) is much more basic (and slightly out dated) but will show you the basics. – kylieCatt May 28 '15 at 21:04
  • @IanAuld, Thank you. I'll read it now ! :) – Yura May 28 '15 at 21:13
  • 1
    By the way you do not type in 'http://localhost:8000/hello.py' do it WITHOUT 'hello.py' – Tom-Oliver Heidel May 28 '15 at 21:55
  • @ Tom-Oliver Heidel, in that case, I just get a list of all the files in the directory. In fact, if I dont type the hello.py, how would the server know to execute the :hello.py" and not "some-other-file-I-have.py"...? – Yura May 28 '15 at 22:01

3 Answers3

31

From the http.server docs:

CGIHTTPRequestHandler can be enabled in the command line by passing the --cgi option:

$ python3 -m http.server --bind localhost --cgi 8000

Put your script into cgi_directories:

This defaults to ['/cgi-bin', '/htbin'] and describes directories to treat as containing CGI scripts.

Open in the browser:

$ python -mwebbrowser http://localhost:8000/cgi-bin/hello.py

where hello.py:

#!/usr/bin/env python3
print("Content-Type: text/html\n")
print("<!doctype html><title>Hello</title><h2>hello world</h2>")

I had to make it executable on POSIX: chmod +x cgi-bin/hello.py.

jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • 1
    can you test my python3 script if it really works. I do not want to install python3 right now or use some online python because those work some different. – Tom-Oliver Heidel May 28 '15 at 20:50
  • 1
    @Tom-OliverHeidel: sure. What commands do you want me to run and what do you expect to happen (define "really works": do you care about multiple concurrent clients, security, buffers, etc)? – jfs May 28 '15 at 20:56
  • 1
    scroll down a bit - the other answer is mine. – Tom-Oliver Heidel May 28 '15 at 21:03
  • @J.F. Sebastian, I did it (except "I had to make it executable on POSIX: chmod +x cgi-bin/hello.py." - since I dont understand what this is. is it Linux? I am on Win) and it did not work for me... stil printing the content of the file onto the browser – Yura May 28 '15 at 21:07
  • 1
    @Yura: 1. have you put `hello.py` into `cgi-bin` directory? 2. Have you appended `--cgi` as shown above? 3. Have you visited `localhost:8000/cgi-bin/hello.py` (note: cgi-bin in url)? 4. Have your added additional `"\r\n"` after the http header? – jfs May 28 '15 at 21:15
  • 1
    @Yura is using windows so. J.F. Sebastian he will not have a cgi-bin by default. I guess he is just testing some python at all. – Tom-Oliver Heidel May 28 '15 at 21:22
  • 1
    @Tom-OliverHeidel: `cgi-bin` is just a directory name: it can be anything from `cgi_directories` (click the link in the answer) – jfs May 28 '15 at 21:25
  • @ J.F. Sebastian. (1)-Yes (2)-Yes (3)-Yes (4)-I guess no, since I have no idea what you are talking about. As for the file, indeed om my screen is printed "hello". BUT, this is just a print of a file and not a result of running it. It I put print("

    hello

    ") instead of the 2nd line , then I would get "

    hello

    " on my screen. Meaning that this is just a print of the file.... :(
    – Yura May 28 '15 at 21:27
  • 1
    @Yura: have you tried to change: `"Content-Type: text/plain\n\nhello\n"` to `"Content-Type: text/html\n\n Hello

    hello world

    "`?
    – jfs May 28 '15 at 21:30
  • @J.F. Sebastian, YOU ARE RIGHT!!!! I have been struggling with it for 3 days. You helped me alot Thank You very much!!! when I put this line as the first one: print ("Content-type:text/html\r\n\r\n") , it does not work. However, when I put this line: print ("Content-Type: text/html\n\n "), it works. Do you know why? – Yura May 28 '15 at 21:53
  • @Yura: If something stops working; start with a known state that works and change **one** thing at a time until it breaks again. `"\n"` is replaced with `"\r\n"` while printing by Python on Windows. [The client (browser) expects `\r\n\r\n` before the html body](http://tools.ietf.org/html/rfc7230#section-3.5). My previous (removed) comment was wrong: [you don't need a space before the field value](http://tools.ietf.org/html/rfc7230#section-3.2.4). There are several html versions. [` ` indicates html5](http://www.w3schools.com/tags/tag_doctype.asp) – jfs May 29 '15 at 08:08
  • How to make the server accept SSL connections, what modifications must be made for this line `python3 -m http.server --bind localhost --cgi 8000`? Thanks – W.M. Jul 14 '16 at 11:09
  • @W.M.: you could add `httpd.socket = ssl.wrap_socket( httpd.socket, keyfile=keypath, certfile=certpath, server_side=True)` to `http.server.test()` function (or use more flexible `SSLContext.wrap_socket`). Here's a [code example for a `python3 -mhttp.server` analog \[text in Russian\]](https://ru.stackoverflow.com/a/780290/23044). For the cgi case, pass CGIHTTPRequestHandler instead of SimpleHTTPRequestHandler – jfs Apr 22 '18 at 12:00
4

I created a complete example for a friend. It is a complete demo you can run with 8 simple copy-paste ready lines of code. Enjoy.

echo -e "\n\n    Usage: after running this script, visit http://localhost:8000/cgi-bin/hello    \n\n"
mkdir /tmp/cgi-bin/
cat > /tmp/cgi-bin/hello <<EOF
#!/bin/bash
echo -e "Content-Type: text/plain\n\n"; date; echo; env
EOF
chmod +x /tmp/cgi-bin/hello
(cd /tmp; python3 -m http.server --cgi 8000)
Bruno Bronosky
  • 66,273
  • 12
  • 162
  • 149
2

I did this some time ago for Python2.7

from BaseHTTPServer import BaseHTTPRequestHandler

class GetHandler(BaseHTTPRequestHandler):

    def do_HEAD(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()

    def do_GET(self):
        x = self.wfile.write
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()
        # <--- HTML starts here --->
        x("<html>")
        # <--- HEAD starts here --->
        x("<head>")
        x("<title>Title goes here!</title>")
        x("</head>")
        # <--- HEAD ends here --->
        # <--- BODY starts here --->
        x("<body>")
        x("<p>This is a test.</p>")
        x("</body>")
        # <--- BODY ends here --->
        x("</html>")
        # <--- HTML ends here --->

if __name__ == '__main__':
    from BaseHTTPServer import HTTPServer
    server = HTTPServer(('localhost', 777), GetHandler)
    print 'Starting server, use <Ctrl + F2> to stop'
    server.serve_forever()

So in Python 3 you just need to change imports

from http.server import BaseHTTPRequestHandler

class GetHandler(BaseHTTPRequestHandler):

    def do_HEAD(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()

    def do_GET(self):
        x = self.wfile.write
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()
        # <--- HTML starts here --->
        x("<html>")
        # <--- HEAD starts here --->
        x("<head>")
        x("<title>Title goes here!</title>")
        x("</head>")
        # <--- HEAD ends here --->
        # <--- BODY starts here --->
        x("<body>")
        x("<p>This is a test.</p>")
        x("</body>")
        # <--- BODY ends here --->
        x("</html>")
        # <--- HTML ends here --->

if __name__ == '__main__':
    from http.server import HTTPServer
    server = HTTPServer(('localhost', 777), GetHandler)
    print('Starting server, use <Ctrl + F2> to stop')
    server.serve_forever()
Chris Huang-Leaver
  • 6,059
  • 6
  • 41
  • 67
Tom-Oliver Heidel
  • 1,011
  • 9
  • 25
  • Thanks @Tom-Oliver Heidel, Im a newbie, please guide me what to do with this code you have posted and where to place it to make my hello-world.py work oin the browser. Thanks – Yura May 28 '15 at 20:44
  • 1
    I cannot guarantuee 100% that the python3 code will work because I just used python docs in short time. But there is a tool called '2to3' which will convert python2 script into python3 script https://docs.python.org/2/glossary.html#term-to3 Actually you just need to copy the scripty and name it like e.g. 'httpserver.py' then you can use cmd and type in 'python httpserver.py' to start it. – Tom-Oliver Heidel May 28 '15 at 20:48
  • 2
    I've changed `777` to `7777` (permission error on Unix) and replaced all `str` literals by `bytes` literals on Python 3. `Ctrl + F2` does something unrelated on my Ubuntu machine. After that it shows: "This is a test." if you visit: `localhost:7777`. – jfs May 28 '15 at 21:14
  • @Tom-OliverHeidel How should I run the files? On port 777? – Yura May 28 '15 at 21:14
  • Thank you @J.F.Sebastian yes I just choose an unused port (win7). Ctrl+F2 was the IDE I am working with - actually in console you abort with ctrl+c. But it seems everything is running fine then :) – Tom-Oliver Heidel May 28 '15 at 21:19
  • 1
    @Yura when you got the file saved and executed with 'python filename.py' you can go and open your browser. type in 'localhost:777' or to whatever you changed the port in the script. – Tom-Oliver Heidel May 28 '15 at 21:20
  • @ Tom-Oliver Heidel, Ok, I did it. saved and run the server file and then typed "http://localhost:777/hello.py" in the browser. => the browser showed a blank page... – Yura May 28 '15 at 21:33
  • 1
    I never said to type in 'localhost:777/hello.py' when you executing the python file you can read 'Starting server ........' then you type into your browser 'localhost:777' nothing more. – Tom-Oliver Heidel May 28 '15 at 21:52
  • @Tom-Oliver Heidel, I just tried typing only "localhost:777" but got a blank result again. Anyway, seems that J.F. Sebastian solved the problem. Thank you very much Tom-OliverHeide for you support and your time! Thanks! – Yura May 28 '15 at 21:57