18

更新:为了便于阅读,这里是如何在反应器关闭之前添加回调:

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

原始问题如下。


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

4

2 回答 2

31

如果您真的非常想专门捕获 Cc,那么您可以以 Python 应用程序的通常方式执行此操作 - 使用signal.signal安装一个处理程序来SIGINT执行您想做的任何事情。如果您从处理程序调用任何 Twisted API,请确保使用,reactor.callFromThread因为几乎所有其他 Twisted API 对于从信号处理程序调用都是不安全的。

However, if you're really just interested in inserting some shutdown-time cleanup code, then you probably want to use IService.stopService (or the mechanism in terms of which it is implemented,reactor.addSystemEventTrigger) instead.

If you're using twistd, then using IService.stopService is easy. You already have an Application object with at least one service attached to it. You can add another one with a custom stopService method that does your shutdown work. The method is allowed to return a Deferred. If it does, then the shutdown process is paused until that Deferred fires. This lets you clean up your connections nicely, even if that involves some more network (or any other asynchronous) operations.

If you're not using twistd, then using reactor.addSystemEventTrigger directly is probably easier. You can install a before shutdown trigger which will get called in the same circumstance IService.stopService would have been called. This trigger (just any callable object) can also return a Deferred to delay shutdown. This is done with a call to reactor.addSystemEventTrigger('before', 'shutdown', callable) (sometime before shutdown is initiated, so that it's already registered whenever shutdown does happen).

service.tac gives an example of creating and using a custom service.

wxacceptance.py gives an example of using addSystemEventTrigger and delaying shutdown by (an arbitrary) three seconds.

Both of these mechanisms will give you notification whenever the reactor is stopping. This may be due to a C-c keystroke, or it may be because someone used kill -INT ..., or it may be because somewhere reactor.stop() was called. They all lead to reactor shutdown, and reactor shutdown always processes shutdown event triggers.

于 2010-08-10T22:29:59.900 回答
2

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

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

如果您将服务器编写为应用程序。子类从twisted.application.service.Service和定义startServicestopService。维护活动协议实例的列表。用于stopService穿过它们并优雅地关闭它们。

如果您有客户端,您也可以子类化Service,但使用起来可能更简单reactor.addSystemEventTrigger('before','shutdown',myCleanUpFunction),并在此函数中优雅地关闭连接。

于 2010-08-10T22:28:07.667 回答