Vor dem Beenden des Programms etwas tun

100

Wie können Sie eine Funktion oder etwas haben, das ausgeführt wird, bevor Ihr Programm beendet wird? Ich habe ein Skript, das ständig im Hintergrund ausgeführt wird, und ich benötige es, um einige Daten in einer Datei zu speichern, bevor es beendet wird. Gibt es eine Standardmethode dafür?

Rennauto
quelle
2
Das Skript sollte niemals aufhören, aber vielleicht wird jemand den Prozess abbrechen oder Strg + \ oder so drücken.
RacecaR

Antworten:

165

Überprüfen Sie das atexitModul:

http://docs.python.org/library/atexit.html

Wenn ich beispielsweise eine Nachricht drucken wollte, als meine Anwendung beendet wurde:

import atexit

def exit_handler():
    print 'My application is ending!'

atexit.register(exit_handler)

Beachten Sie jedoch, dass dies für die normale Beendigung des Skripts hervorragend funktioniert, jedoch nicht in allen Fällen aufgerufen wird (z. B. schwerwiegende interne Fehler).

Brent schreibt Code
quelle
5
Gibt es eine Möglichkeit, es dahin zu bringen, wo es aufgerufen wird, wenn Sie Strg + C oder Strg + \ drücken?
RacecaR
8
Es wird aufgerufen, wenn Sie Strg + C drücken. Das löst einfach eine KeyboardInterrupt-Ausnahme aus.
Ned Batchelder
1
Oh, das habe ich vergessen. Und ich gehe davon aus, dass nichts, was Sie tun können, ausgeführt wird, wenn jemand den Python-Prozess beendet, oder?
RacecaR
5
@RacecaR: in der Tat; Der Punkt, einen Prozess zu beenden, besteht darin, ihn tot zu halten. Aus den Dokumenten : Note The exit function is not called when the program is killed by a signal, when a Python fatal internal error is detected, or when os._exit() is called.
Katriel
18
@RacecaR, die einzige Möglichkeit, den Beendigungscode auszuführen, selbst wenn ein Prozess schwer abstürzt oder brutal beendet wird, ist ein anderer Prozess, der als "Monitor" oder "Watchdog" bezeichnet wird und dessen einzige Aufgabe darin besteht , den Zielprozess und zu überwachen Führen Sie den Beendigungscode aus, wenn dies angemessen ist. Das erfordert natürlich eine ganz andere Architektur und hat seine Grenzen. Wenn Sie eine solche Funktionalität benötigen, ist es am besten, wenn Sie ein anderes Q in dieser Angelegenheit öffnen.
Alex Martelli
32

Wenn Sie möchten, dass auch bei Fehlern immer etwas ausgeführt wird, verwenden Sie try: finally:Folgendes:

def main():
    try:
        execute_app()
    finally:
        handle_cleanup()

if __name__=='__main__':
    main()

Wenn Sie auch Ausnahmen behandeln möchten, können Sie eine except:vor dem einfügenfinally:

Brian C. Lane
quelle
13
Funktioniert nicht, wenn SIGTERM aufgrund eines Abbruchs des Prozesses auftritt.
Ramu
16

Wenn Sie das Skript stoppen, indem Sie a auslösen KeyboardInterrupt(z. B. durch Drücken von Strg-C), können Sie dies nur als Standardausnahme abfangen. Sie können auch SystemExitauf die gleiche Weise fangen .

try:
    ...
except KeyboardInterrupt:
    # clean up
    raise

Ich erwähne dies nur, damit Sie davon erfahren. Der "richtige" Weg, dies zu tun, ist das atexitoben erwähnte Modul.

Katriel
quelle