Python 3.x BaseHTTPServer или http.server
Я пытаюсь сделать программу BaseHTTPServer. Я предпочитаю использовать Python 3.3 или 3.2 для него. Я нахожу документ трудным для понимания относительно того, что импортировать, но попытался изменить импорт с:
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
чтобы:
from http.server import BaseHTTPRequestHandler,HTTPServer
и затем импорт работает, и программа запускается и ожидает GET-запроса. НО, когда приходит запрос, возникает исключение:
File "C:\Python33\lib\socket.py", line 317, in write return self._sock.send(b)
TypeError: 'str' does not support the buffer interface
Вопрос: существует ли версия BaseHTTPServer или http.server, которая работает из коробки с Python3.x или я что-то не так делаю?
Это "моя" программа, которую я пытаюсь запустить в Python 3.3 и 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()
Программа частично работает в Python2.7, но выдает это исключение после 2-8 запросов:
error: [Errno 10054] An existing connection was forcibly closed by the remote host
3 ответа
Ваша программа на python 3.xx работает прямо из коробки - за исключением одной незначительной проблемы. Проблема не в вашем коде, а в том месте, где вы пишете эти строки:
self.wfile.write("Hello World !")
Вы пытаетесь написать "строку" там, но байты должны идти туда. Поэтому вам нужно преобразовать вашу строку в байты.
Вот, посмотрите мой код, который почти такой же, как у вас, и работает отлично. Это написано в 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))
Обратите внимание, как я преобразовываю их из строки в байты, используя кодировку "UTF-8". Как только вы сделаете это изменение в вашей программе, ваша программа должна работать нормально.
Вы можете просто сделать так:
self.send_header('Content-type','text/html'.encode())
self.end_headers()
# Send the html message
self.wfile.write("Hello World !".encode())
Кто бы ни делал документацию по python 3 для http.server, он не заметил изменения. Документация 2.7 гласит прямо вверху: "Примечание Модуль BaseHTTPServer был объединен с http.server в Python 3. Инструмент 2to3 автоматически адаптирует импорт при преобразовании ваших источников в Python 3."
Вы должны изменить аргумент wfile, потому что в Python 3 он принимает байты как объекты, поэтому преобразуйте вашу строку в байты следующим образом:
self.wfile.write(b"<h1> Hello </h1>)
Или же
self.wfile.write( bytes("<h1> Hello </h1>) )