如何关闭Python TCPServer或HTTPServer或SimpleHTTPServer?

时间:2014-06-15 03:09:31

标签: python multithreading popen httpserver tcpserver

我正在为C / C ++ HTTP / HTTPS客户端整理测试工具,我想在测试工具中使用python作为服务器。 Python似乎有一组非常好的TCP / HTTP服务器和处理程序类,看起来它将成为完成此任务的阻力最小的路径。

那就是说,我试图弄清楚如何优雅地关闭TCPServer对象。我的测试工具是用C ++编写的,我想使用popen()来调用服务器,因为它不像system()那样有问题,而且它在我所有的目标平台上都可用(Windows,OSX,Linux)。鉴于我使用popen()来启动python服务器,我不会让python进程的PID可用,所以我不能轻易{{1} } 服务器。

我以为我想发送一个' q'服务器进程的STDIN字符,或者将STDIN管道关闭到服务器,发送EOF以使其正常关闭。我无法找到一个非常棒的方法。

当您调用SIGTERM方法时,

TCPServer / HTTPServer /等开始工作。因此,当我在其上调用一个名为.serve_forever()的方法时,我不应该感到惊讶,TCPServer很难让.serve_forever()永远停止服务。作为替代方案,BaseHTTPServer的python文档建议反复调用.handle_request()

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()

但是,它也不能很好地工作 - 它依赖于服务器接收并完成检查是否继续运行的请求 - 如果服务器没有得到请求,它不会#39; t从.handle_request()返回。

TCPServer 有一个名为.shutdown()的方法:

BaseServer.shutdown()
    Tell the serve_forever() loop to stop and wait until it does.

    New in version 2.6.

这是线程安全的吗?我知道GIL,但我仍然想知道这是否被认为是正确的事情,考虑到像PyPy这样的替代python实现。我可以在另一个线程上等待STDIN,然后在STDIN上获得EOF时安全地调用TCPServer的{​​{1}}方法吗?

1 个答案:

答案 0 :(得分:1)

是的,BaseServer.shutdown()方法是线程安全的。

serve_forever方法一直有效,直到设置了shutdown标志,并且设置该标志是shutdown()的任务。该方法在docstring:

中说明
  

阻止循环结束。必须在此时调用   serve_forever()在另一个线程中运行,否则会死锁。

请注意,这与GIL无关;这只限制了Python进程可以有效利用C扩展和I / O之外的多少核心。