Steven Lu
Steven Lu

Reputation: 43417

Python BaseHTTPServer: How to get it to stop?

According to the source the BaseServer.shutdown() must be called from a different thread than the one the server is running on.

However I am trying to shut down the server with a specific value provided to the server in a web request.

The request handler obviously runs in this thread so it will still deadlock after I have done this:

httpd = BaseHTTPServer.HTTPServer(('', 80), MyHandler)
print("Starting server in thread")
threading.Thread(target=httpd.serve_forever).start()

How can I accomplish what I want? Must I set up a socket or pipe or something (please show me how to do this, if it is the solution), where the main thread can block and wait on the child thread to send a message, at which point it will be able to call shutdown()?

I am currently able to achieve some "kind of works" behavior by calling "httpd.socket.close()" from the request handler. This generates an [Errno 9] Bad file descriptor error and seems to terminate the process on Windows.

But this is clearly not the right way to go about this.

Update ca. Aug. 2013 I have eloped with node.js to fill the need for robust async I/O, but plenty of side projects (e.g. linear algebra research, various command line tool frontends) keep me coming back to python. Looking back on this question, BaseHTTPServer probably has little practical value comparatively to other options (like various microframeworks that Phil mentions).

Upvotes: 2

Views: 6355

Answers (2)

Phil Cooper
Phil Cooper

Reputation: 5877

1. from the BaseHTTPServer docs

To create a server that doesn’t run forever, but until some condition is fulfilled:

def run_while_true(server_class=BaseHTTPServer.HTTPServer,
                   handler_class=BaseHTTPServer.BaseHTTPRequestHandler):
    """
    This assumes that keep_running() is a function of no arguments which
    is tested initially and after each request.  If its return value
    is true, the server continues.
    """
    server_address = ('', 8000)
    httpd = server_class(server_address, handler_class)
    while keep_running():
        httpd.handle_request()

Allow some url call to set the condition to terminate, use whatever strikes your fancy there.

Edit: keep_running is any function you choose, could be as simple as:

def keep_running():
    global some_global_var_that_my_request_controller_will_set
    return some_global_var_that_my_request_controller_will_set 

you probably want something smarter and without_rediculously_long_var_names.

2. BaseHTTPServer is usually lower than you want to go. There are plenty of micro-frameworks that might suit your needs

Upvotes: 3

ephemient
ephemient

Reputation: 204668

threading.Event is useful for signalling other threads. e.g.,

please_die = threading.Event()

# in handler
please_die.set()

# in main thread
please_die.wait()
httpd.shutdown()

You might use a Queue if you want to send data between threads.

Upvotes: 2

Related Questions