python - 如何关闭 Python TCPServer 或 HTTPServer 或 SimpleHTTPServer?

标签 python multithreading popen httpserver tcpserver

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

就是说,我正在尝试弄清楚如何优雅地关闭 TCPServer 对象。我的测试工具是用 C++ 编写的,我想使用 popen() 来调用服务器,只是因为它不像 system() 那样有问题,它的在我的所有目标平台(Windows、OSX、Linux)上都可用。鉴于我正在使用 popen() 启动 python 服务器,我将无法使用 python 进程的 PID,因此我无法轻松地 SIGTERM服务器。

我认为我想向服务器进程的 STDIN 发送一个“q”字符,或者关闭到服务器的 STDIN 管道,向其发送 EOF 以使其正常关闭。我只是想不出一个真正好的方法来做到这一点。

TCPServer/HTTPServer/et al 在您调用它们的 .serve_forever() 方法时开始它们的工作。所以我想当我调用一个名为 .serve_forever() 的方法时,很难让 TCPServer 永远停止服务,我不应该感到惊讶。作为替代方案,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()

但这也不是很好 - 它依赖于服务器接收并完成请求以检查是否继续运行 - 如果服务器没有收到请求,它不会从 返回。 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.shutdown() 方法?

最佳答案

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

serve_forever 方法一直服务到设置关闭标志为止,设置该标志是 shutdown() 的任务。该方法在文档字符串中指出:

Blocks until the loop has finished. This must be called while serve_forever() is running in another thread, or it will deadlock.

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

关于python - 如何关闭 Python TCPServer 或 HTTPServer 或 SimpleHTTPServer?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24226210/

相关文章:

java - 为什么这段代码不播放声音文件

python - 我怎样才能知道 os.popen 是否在同一个 shell 中运行 linux 命令?

c++ - 如何判断 popen() 是否成功?

python - 如何对 Keras 中的整个模型应用权重归一化?

.net - 为什么可以对同一个委托(delegate)实例多次调用 BeginInvoke?

multithreading - 有没有办法检测对象是否被锁定?

c++ - 使用管道读取dd命令输出的问题

python - python中列表字典的概率

python - 选择 N 条随机记录

python - 将参数从 python 解析为 C++