The usual Python HTTP server never stops. Since there is the timout option in the socket module, there is an easy way to do a clean shutdown of a running server.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
import SimpleHTTPServer, BaseHTTPServer import socket import thread class StoppableHTTPServer(BaseHTTPServer.HTTPServer): def server_bind(self): BaseHTTPServer.HTTPServer.server_bind(self) self.socket.settimeout(1) self.run = True def get_request(self): while self.run: try: sock, addr = self.socket.accept() sock.settimeout(None) return (sock, addr) except socket.timeout: pass def stop(self): self.run = False def serve(self): while self.run: self.handle_request() if __name__=="__main__": httpd = StoppableHTTPServer(("127.0.0.1",8080), SimpleHTTPServer.SimpleHTTPRequestHandler) thread.start_new_thread(httpd.serve, ()) raw_input("Press <RETURN> to stop server\n") httpd.stop()
We override the server_bind method to set a timeout on the main socket. Then we override the get_request and serve methods to break if the attribute run is set to False. The rest is just for convenience. In the sample script we start the server in a new thread and then wait for stop request by pressing the return key.
This method can be used for all types of servers based on the SocketServer module.
Exception after stopping the server. It took me a while to find this solution for a stoppable server. So I am very happy with it. However...
The server ends with an exception because get_request returns nothing with a timeout and handle_request tries to handle that nothing.
Solution. The problem above might be caused by the fact that my implementation is a bit different (it is a SimpleXMLRpcServer i.s.o. a HTTPServer).
The/a solution to my problem is to return (None,None) in get_request and handle a None request in also override close_request and process_request to handle the special case where the request is None. Heres the result.
Questions remain: Has anyone found a better solution for this (it seems cumbersome)? Is there something like an empty request - making it possible to remove some ifs?
Yes, there is a very simple solutions to kill the ifs... If you look at the implementation of SocketServer, you will see that handle_request does:
So, if get_request raises a socket exception, then it exits cleanly and does not bother to call verify/process/close_request. So, just do this: