Fare qualcosa prima dell'uscita dal programma


100

Come puoi avere una funzione o qualcosa che verrà eseguito prima che il tuo programma si chiuda? Ho uno script che sarà costantemente in esecuzione in background e ne ho bisogno per salvare alcuni dati in un file prima che esca. Esiste un modo standard per farlo?


2
Lo script non dovrebbe mai interrompersi, ma forse qualcuno ucciderà il processo o premerà Ctrl + \ o qualcosa del genere.
RacecaR

Risposte:


165

Controlla il atexitmodulo:

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

Ad esempio, se volessi stampare un messaggio quando la mia applicazione stava per terminare:

import atexit

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

atexit.register(exit_handler)

Basta essere consapevoli che questo funziona alla grande per la normale terminazione dello script, ma non verrà chiamato in tutti i casi (ad esempio errori interni fatali).


5
C'è un modo per farlo dove verrà chiamato se premi Ctrl + C o Ctrl + \?
RacecaR

8
Sarà chiamato se premi Ctrl + C. Questo solleva semplicemente un'eccezione KeyboardInterrupt.
Ned Batchelder

1
Oh, l'ho dimenticato. E presumo che nulla che tu possa fare verrà eseguito se qualcuno uccide il processo Python, giusto?
RacecaR

5
@RacecaR: infatti; lo scopo di uccidere un processo è fermarlo. Dalla documentazione: 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, l'unico modo per eseguire il codice di terminazione anche se un processo si blocca gravemente o viene brutalmente ucciso è in un altro processo, noto come "monitor" o "watchdog", il cui unico compito è tenere d'occhio il processo di destinazione e eseguire il codice di terminazione quando appropriato. Ovviamente ciò richiede un'architettura molto diversa e ha i suoi limiti; se hai bisogno di tale funzionalità, è meglio che tu apra una Q diversa sull'argomento.
Alex Martelli

32

Se vuoi che qualcosa funzioni sempre, anche in caso di errori, usa try: finally:questo:

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

if __name__=='__main__':
    main()

Se vuoi gestire anche le eccezioni puoi inserire una except:prima del filefinally:


13
Non funziona quando si verifica SIGTERM a causa dell'uccisione del processo.
ramu

16

Se interrompi lo script alzando a KeyboardInterrupt(ad esempio premendo Ctrl-C), puoi prenderlo come un'eccezione standard. Puoi anche catturare SystemExitallo stesso modo.

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

Lo menziono solo per farti sapere a riguardo; il modo "giusto" per farlo è il atexitmodulo menzionato sopra.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.