2010-08-10 4 views
15

UPDATE: Zur Erleichterung des Lesens, hier ist, wie ein Rückruf hinzufügen, bevor die Reaktorabschaltung wird:twisted: Fang KeyboardInterrupt und Abschaltung richtig

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

Original Frage folgt.


Wenn ich einen Client mit einem Server haben, und es ist chilling im Hauptschleifenreaktor Warten auf Ereignisse, wenn ich STRG + C treffen, erhalte ich eine „Verbindung zur anderen Seite wurde in einem nicht verloren Saubere Mode: Verbindung verloren. " Wie kann ich es einrichten, so dass ich weiß, wenn ein KeyboardInterrupt passiert, so dass ich sauber säubern und sauber trennen kann? Oder wie kann ich einen saubereren Weg zum Herunterfahren implementieren, der nicht CTRL-C beinhaltet, wenn möglich?

+0

süß, erster Schlag auf googling "verdreht vor dem Herunterfahren"! – Claudiu

Antwort

29

Wenn Sie wirklich, wirklich C-c spezifisch fangen möchten, dann können Sie dies in der üblichen Weise für eine Python-Anwendung tun - verwenden Sie signal.signal, um einen Handler für SIGINT zu installieren, der tut, was Sie tun möchten. Wenn Sie Twisted-APIs vom Handler aufrufen, stellen Sie sicher, dass Sie reactor.callFromThread verwenden, da fast alle anderen Twisted-APIs für den Aufruf von Signalhandlern unsicher sind.

Wenn Sie jedoch nur daran interessiert sind, einen Cleanup-Code für die Abschaltzeit hinzuzufügen, möchten Sie wahrscheinlich stattdessen IService.stopService (oder den Mechanismus, in dem es implementiert ist, reactor.addSystemEventTrigger) verwenden. Wenn Sie twistd verwenden, ist die Verwendung von IService.stopService einfach. Sie haben bereits ein Application Objekt mit mindestens einem Service. Sie können einen weiteren mit einer benutzerdefinierten stopService Methode hinzufügen, die Ihre Shutdown-Arbeit erledigt. Die Methode darf Deferred zurückgeben. Wenn dies der Fall ist, wird der Abschaltvorgang angehalten, bis Deferred ausgelöst wird. Auf diese Weise können Sie Ihre Verbindungen sauber bereinigen, auch wenn dies einige Netzwerkoperationen (oder andere asynchrone Vorgänge) erfordert. Wenn Sie twistd nicht verwenden, ist die Verwendung von reactor.addSystemEventTrigger direkt wahrscheinlich einfacher. Sie können einen vor dem Shutdown Trigger installieren, der unter den gleichen Umständen IService.stopService aufgerufen würde aufgerufen werden würde. Dieser Trigger (nur ein beliebiges aufrufbares Objekt) kann auch eine Deferred zurückgeben, um das Herunterfahren zu verzögern. Dies geschieht mit einem Aufruf an reactor.addSystemEventTrigger('before', 'shutdown', callable) (irgendwann bevor das Herunterfahren initiiert wird, so dass es bereits registriert ist, wenn ein Herunterfahren stattfindet).

service.tac gibt ein Beispiel zum Erstellen und Verwenden eines benutzerdefinierten Dienstes.

wxacceptance.py gibt ein Beispiel für die Verwendung von addSystemEventTrigger und verzögern Herunterfahren um (eine beliebige) drei Sekunden.

Diese beiden Mechanismen geben Ihnen die Meldung immer wenn der Reaktor stoppt. Dies kann auf einen C-c-Tastenanschlag zurückzuführen sein, oder es kann sein, dass jemand kill -INT ... verwendet, oder es könnte sein, weil irgendwo reactor.stop() aufgerufen wurde. Sie führen alle zur Abschaltung des Reaktors, und die Abschaltung des Reaktors verarbeitet immer Abschaltungsereignisse.

+0

+1 - Wusste nicht über die zurückgehenden Deferreds! – MattH

+0

perfekt! funktionierte genau so, wie ich es mochte. jetzt nach Monaten der hässlichen Reinigung ist es endlich schön und schön ... – Claudiu

1

Ich bin mir nicht sicher, ob Sie über einen Client oder einen Server sprechen, den Sie geschrieben haben.

Wie auch immer, nichts ist falsch mit 'CTRL-C'.

Wenn Sie einen Server als Anwendung schreiben. Unterklasse von twisted.application.service.Service und definieren startService und stopService. Pflegen Sie eine Liste der aktiven Protokollinstanzen. Verwenden Sie stopService, um durch sie hindurchzugehen und sie anmutig zu schließen.

Wenn Sie einen Client haben, könnten Sie auch die Unterklasse Service, aber es könnte einfacher sein, reactor.addSystemEventTrigger('before','shutdown',myCleanUpFunction) zu verwenden, und schließen Sie die Verbindung (en) elegant in dieser Funktion.