5

我已经在这篇文章中读到,使用ThreadingMixin(来自SocketServer模块),您可以使用BaseHTTPServer. 我已经尝试过了,它确实有效。但是,如何停止服务器产生的活动线程(例如,在服务器关闭期间)?这可能吗?

4

2 回答 2

8

最简单的解决方案是只使用daemon_threads. 简短的版本是:只需将其设置为 True,不用担心;当您退出时,任何仍在工作的线程都会自动停止。

正如ThreadingMixIn文档所说:

当从 ThreadingMixIn 继承线程连接行为时,您应该明确声明您希望线程在突然关闭时的行为方式。ThreadingMixIn 类定义了一个属性 daemon_threads,它指示服务器是否应该等待线程终止。如果您希望线程自主运行,则应显式设置该标志;默认值为 False,这意味着 Python 在 ThreadingMixIn 创建的所有线程都退出之前不会退出。

threading文档中提供了更多详细信息:

可以将线程标记为“守护线程”。这个标志的意义在于,当只剩下守护线程时,整个 Python 程序就退出了。初始值继承自创建线程。可以通过 daemon 属性设置标志。

有时这是不合适的,因为您想在不退出的情况下关闭,或者因为您的处理程序可能需要进行清理。但在适当的时候,你不能变得更简单。

如果您只需要一种在不退出的情况下关闭的方法,并且不需要保证清理,您可以通过ctypes或使用特定于平台的线程取消 API win32api。这通常是一个坏主意,但有时这正是您想要的。

如果您需要彻底关闭,则需要为此构建自己的机器,线程协作的地方。例如,您可以创建一个由 a 保护的全局“退出标志”变量threading.Condition,并让您的handle函数定期检查它。

如果线程只是在做缓慢的、非阻塞的工作,你可以把它分解成更小的部分,那就太好了。例如,如果该handle函数始终至少每 5 秒检查一次退出标志,则可以保证能够在 5 秒内关闭线程。但是如果线程正在做阻塞工作——因为它们可能是这样,因为你使用的全部原因ThreadingMixIn是让你进行阻塞调用而不是编写select循环或使用asyncore等?

好吧,没有好的答案。显然,如果您只需要“最终”而不是“在 5 秒内”发生关闭(或者如果您愿意在 5 秒后放弃干净关闭,并恢复使用特定于平台的 API 或守护线程),您只需在每次阻塞调用之前和之后进行检查,它就会“经常”工作。但如果这还不够好,你真的无能为力。

如果你需要这个,最好的答案是改变你的架构以使用有办法做到这一点的框架。最受欢迎的选择是TwistedTornadogevent。将来,PEP 3156会将类似的功能引入标准库,tulip如果您不想为现实世界构建一些必须尽快准备好的东西,那么有一个部分完整的参考实现值得一玩。

于 2013-01-11T19:10:50.767 回答
0

下面的示例代码展示了如何使用 threading.Event 在任何 POST 请求上关闭服务器,

import SocketServer
import BaseHTTPServer
import threading

quit_event = threading.Event()

class MyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
  """This handler fires the quit event on POST."""
  def do_GET(self):
    self.send_response(200)
  def do_POST(self):
    quit_event.set()
    self.send_response(200)


class MyThreadingHTTPServer(
    SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
  pass

server = MyThreadingHTTPServer(('', 8080), MyRequestHandler)
threading.Thread(target=server.serve_forever).start()
quit_event.wait()
server.shutdown()

服务器已完全关闭,因此您可以立即重新启动服务器并且端口可用,而不是获得“地址已在使用中”。

于 2014-01-29T15:43:25.917 回答