Python 3.x BaseHTTPServer or http.server

2020-05-13 20:22发布

问题:

I am trying to make a BaseHTTPServer program. I prefer to use Python 3.3 or 3.2 for it. I find the doc hard to understand regarding what to import but tried changing the import from:

from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer

to:

from http.server import BaseHTTPRequestHandler,HTTPServer

and then the import works and the program start and awaits a GET request. BUT when the request arrives an exception is raised:

File "C:\Python33\lib\socket.py", line 317, in write return self._sock.send(b)
TypeError: 'str' does not support the buffer interface

Question: Is there a version of BaseHTTPServer or http.server that works out of the box with Python3.x or am I doing something wrong?

This is "my" program that I try running in Python 3.3 and 3.2:

#!/usr/bin/python
# from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
from http.server import BaseHTTPRequestHandler,HTTPServer

PORT_NUMBER = 8080

# This class will handle any incoming request from
# a browser 
class myHandler(BaseHTTPRequestHandler):

    # Handler for the GET requests
    def do_GET(self):
        print   ('Get request received')
        self.send_response(200)
        self.send_header('Content-type','text/html')
        self.end_headers()
        # Send the html message
        self.wfile.write("Hello World !")
        return

try:
    # Create a web server and define the handler to manage the
    # incoming request
    server = HTTPServer(('', PORT_NUMBER), myHandler)
    print ('Started httpserver on port ' , PORT_NUMBER)

    # Wait forever for incoming http requests
    server.serve_forever()

except KeyboardInterrupt:
    print ('^C received, shutting down the web server')
    server.socket.close()

The Program work partly in Python2.7 but gives this exception after 2-8 requests:

error: [Errno 10054] An existing connection was forcibly closed by the remote host

回答1:

Your program in python 3.xx does work right out of the box - except for one minor problem. The issue is not in your code but the place where you are writing these lines:

self.wfile.write("Hello World !")

You are trying to write "string" in there, but bytes should go there. So you need to convert your string to bytes.

Here, see my code, which is almost same as you and works perfectly. Its written in python 3.4

from http.server import BaseHTTPRequestHandler, HTTPServer
import time

hostName = "localhost"
hostPort = 9000

class MyServer(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()
        self.wfile.write(bytes("<html><head><title>Title goes here.</title></head>", "utf-8"))
        self.wfile.write(bytes("<body><p>This is a test.</p>", "utf-8"))
        self.wfile.write(bytes("<p>You accessed path: %s</p>" % self.path, "utf-8"))
        self.wfile.write(bytes("</body></html>", "utf-8"))

myServer = HTTPServer((hostName, hostPort), MyServer)
print(time.asctime(), "Server Starts - %s:%s" % (hostName, hostPort))

try:
    myServer.serve_forever()
except KeyboardInterrupt:
    pass

myServer.server_close()
print(time.asctime(), "Server Stops - %s:%s" % (hostName, hostPort))

Please notice the way I convert them from string to bytes using the "UTF-8" encoding. Once you do this change in your program, your program should work fine.



回答2:

You can just do like that:

self.send_header('Content-type','text/html'.encode())
self.end_headers()
# Send the html message
self.wfile.write("Hello World !".encode())


回答3:

Whoever did the python 3 documentation for http.server failed to note the change. The 2.7 documentation states right at the top "Note The BaseHTTPServer module has been merged into http.server in Python 3. The 2to3 tool will automatically adapt imports when converting your sources to Python 3."



回答4:

You should change wfile argument, because in Python 3 it accept bytes like objects, therefore convert your string to bytes by:

self.wfile.write(b"<h1> Hello </h1>)

Or

self.wfile.write( bytes("<h1> Hello </h1>) )