使用ThreadingMixin停止BaseHTTPServer生成的线程

时间:2013-01-11 19:02:50

标签: python multithreading python-2.7 basehttpserver

我已在this post上阅读了ThreadingMixin(来自SocketServer模块),您可以使用BaseHTTPServer创建一个线程服务器。我试过了, 工作了。但是,如何停止服务器生成的活动线程(例如,在服务器关闭期间)?这可能吗?

2 个答案:

答案 0 :(得分:7)

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

正如ThreadingMixIn docs所说:

  

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

threading docs

中提供了更多详细信息
  

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

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

如果你需要的只是一种在不退出的情况下关闭的方法,并且不需要保证清理,你可以通过ctypeswin32api使用特定于平台的线程消除API。这通常是一个坏主意,但偶尔也是你想要的。

如果您需要干净关闭,您需要为线程配合构建自己的机器。例如,您可以创建一个受threading.Condition保护的全局“退出标记”变量,并让您的handle函数定期检查。

如果线程正在执行缓慢,无阻塞的工作,您可以分解成更小的部分,这是非常好的。例如,如果handle函数始终每5秒至少检查一次退出标志,则可以保证能够在5秒内关闭线程。但是如果线程正在进行阻塞工作会怎么样 - 因为你使用ThreadingMixIn的原因是让你进行阻塞调用而不是编写select循环或使用asyncore或之类的?

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

如果您需要,最好的答案是更改您的架构以使用具有此方法的框架。最受欢迎的选择是TwistedTornadogevent。将来,PEP 3156会在标准库中引入类似的功能,并且如果你没有尝试为现实世界构建一些东西,那么值得玩的是部分完整的参考实现tulip准备好了。

答案 1 :(得分: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()

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