2010-08-10 9 views
15

ACTUALIZACIÓN: Para facilitar la lectura, aquí es cómo añadir una devolución de llamada antes de que el reactor se pone apagado:twisted: KeyboardInterrupt captura y apagado correctamente

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

pregunta original sigue.


Si tengo un cliente conectado a un servidor, y es escalofriante en el bucle principal del reactor a la espera de acontecimientos, cuando golpeo CTRL-C, aparece un "Conexión a la otra parte se perdió en un no -la moda limpia: Conexión perdida ". ¿Cómo puedo configurarlo para que sepa cuándo ocurre una interferencia de teclado, para que pueda hacer una limpieza adecuada y desconectarme limpiamente? ¿O cómo puedo implementar una forma más limpia de apagado que no implique CTRL-C, si es posible?

+0

dulce, primer golpe en google "retorcido antes del cierre"! – Claudiu

Respuesta

29

Si realmente desea capturar C-c específicamente, puede hacerlo de la manera habitual para una aplicación de Python: use signal.signal para instalar un controlador para SIGINT que haga lo que quiera hacer. Si invoca cualquier API retorcida desde el controlador, asegúrese de usar reactor.callFromThread ya que casi todas las demás API retorcidas no son seguras para la invocación de manejadores de señal.

Sin embargo, si realmente está interesado en insertar algún código de limpieza de tiempo de apagado, entonces probablemente desee utilizar IService.stopService (o el mecanismo en términos de los cuales se implementó, reactor.addSystemEventTrigger).

Si está usando twistd, entonces usar IService.stopService es fácil. Ya tiene un objeto Application con al menos un servicio adjunto. Puede agregar otro con un método personalizado stopService que hace que su cierre funcione. El método puede devolver un Deferred. Si lo hace, el proceso de apagado se pausa hasta que se dispare Deferred. Esto le permite limpiar bien sus conexiones, incluso si eso implica más operaciones de red (o cualquier otra asincrónica).

Si no está usando twistd, entonces usar reactor.addSystemEventTrigger directamente es probablemente más fácil. Puede instalar un antes de apagar el disparador que se llamará en la misma circunstancia en que se haya llamado al IService.stopService. Este disparador (cualquier objeto que se pueda llamar) también puede devolver un Deferred para retrasar el apagado. Esto se hace con una llamada al reactor.addSystemEventTrigger('before', 'shutdown', callable) (en algún momento antes de que se inicie el apagado, de modo que ya está registrado cada vez que se produce el apagado).

service.tac da un ejemplo de creación y uso de un servicio personalizado.

wxacceptance.py da un ejemplo del uso de addSystemEventTrigger y retrasa el apagado por (un arbitrario) tres segundos.

Ambos de estos mecanismos le darán la notificación cada vez que se detenga el reactor. Esto puede deberse a una pulsación de tecla C-c, o puede ser porque alguien usó kill -INT ..., o puede ser porque se llamó a algún lugar reactor.stop(). Todos conducen al cierre del reactor, y el cierre del reactor siempre procesa los desencadenantes de eventos de cierre.

+0

+1 - ¡No sabía acerca de los Deferreds que regresan! – MattH

+0

¡perfecto! funcionó exactamente como me gustaba. ahora después de meses de tener una limpieza fea, finalmente es agradable y bonita ... – Claudiu

1

No estoy seguro de si está hablando de un cliente o servidor que ha escrito.

De todos modos, nada de malo con 'CTRL-C'.

Si está escribiendo un servidor como una Aplicación. Subclase de twisted.application.service.Service y defina startService y stopService. Mantenga una lista de instancias de protocolo activas. Use stopService para revisarlos y cerrarlos con gracia.

Si tiene un cliente, también podría crear la subclase Service, pero podría ser más simple usar reactor.addSystemEventTrigger('before','shutdown',myCleanUpFunction), y cerrar la (s) conexión (es) correctamente en esta función.