twisted:正确捕获keyboardinterrupt和shutdown

时间:2010-08-10 21:09:42

标签: python twisted shutdown

更新:为了便于阅读,以下是在反应堆关闭之前添加回调的方法:

reactor.addSystemEventTrigger('before', 'shutdown', callable)

原始问题如下。


如果我有一个连接到服务器的客户端,并且它在反应器主循环中等待事件的冷却,当我按下CTRL-C时,我得到一个“以另一方面的连接以非干净的方式丢失:连接丢失了。“如何设置它以便我知道何时发生KeyboardInterrupt,以便我可以进行适当的清理并彻底断开连接?或者,如果可能的话,如何实现更清晰的关闭方式,不涉及CTRL-C?

2 个答案:

答案 0 :(得分:30)

如果你真的,真的想特别抓住Cc,那么你可以通常的方式为Python应用程序执行此操作 - 使用signal.signal安装SIGINT的处理程序,它可以执行任何您想要的操作做。如果从处理程序调用任何Twisted API,请确保使用reactor.callFromThread,因为几乎所有其他Twisted API对于从信号处理程序调用都是不安全的。

但是,如果您真的只是想插入一些关机时清理代码,那么您可能希望使用IService.stopService(或实现它的机制,reactor.addSystemEventTrigger)代替。

如果您使用的是twistd,那么使用IService.stopService很容易。您已经有一个Application对象,其中至少附加了一个服务。您可以使用自定义stopService方法添加另一个方法来执行关机工作。允许该方法返回Deferred。如果是,则关闭过程暂停,直到Deferred触发。这使您可以很好地清理连接,即使这涉及更多的网络(或任何其他异步)操作。

如果您未使用twistd,则直接使用reactor.addSystemEventTrigger可能会更容易。您可以在关闭之前安装 触发器,该触发器将在调用IService.stopService的同一情况下被调用。此触发器(只是任何可调用对象)也可以返回Deferred以延迟关闭。这是通过调用reactor.addSystemEventTrigger('before', 'shutdown', callable)来完成的(在启动关闭之前的某个时间,以便在发生关闭时它已经注册)。

service.tac提供了创建和使用自定义服务的示例。

wxacceptance.py给出了一个使用addSystemEventTrigger并将关闭延迟(任意)三秒的示例。

每当反应堆停止时,这两种机制都会给你通知。这可能是由于C-c键击,或者可能是因为某人使用了kill -INT ...,或者可能是因为调用某处reactor.stop()。它们都导致反应堆关闭,反应堆关闭总是处理关闭事件触发器。

答案 1 :(得分:1)

我不确定你是在谈论你写的客户端还是服务器。

无论如何,'CTRL-C'没有错。

如果您正在将服务器编写为应用程序。来自twisted.application.service.Service的子类,并定义startServicestopService。维护活动协议实例列表。使用stopService浏览它们并优雅地关闭它们。

如果你有一个客户端,你也可以继承Service,但是使用reactor.addSystemEventTrigger('before','shutdown',myCleanUpFunction)可能更简单,并且在这个函数中优雅地关闭连接。