2011-08-22 17 views
6

Voglio eseguire un'attività quando termina il mio programma Python, ma solo se termina correttamente. Per quanto ne so, l'uso del modulo atexit significa che la mia funzione registrata sarà sempre in esecuzione, a prescindere dal successo. Esiste una funzionalità simile per registrare una funzione in modo che venga eseguita solo in caso di esito positivo? In alternativa, c'è un modo per la mia funzione di uscita per rilevare se l'uscita era normale o eccezionale?Come posso registrare una funzione da chiamare solo su * esito positivo * dell'uscita del mio programma Python?

Ecco un codice che dimostra il problema. Stamperà che il programma è riuscito, anche quando ha fallito.

import atexit 

def myexitfunc(): 
    print "Program succeeded!" 

atexit.register(myexitfunc) 

raise Exception("Program failed!") 

uscita:

$ python atexittest.py 
Traceback (most recent call last): 
    File "atexittest.py", line 8, in <module> 
    raise Exception("Program failed!") 
Exception: Program failed! 
Program succeeded! 

risposta

4

Fuori dalla scatola, atexit non è del tutto adatto per ciò che si vuole fare: è utilizzato principalmente per la pulizia delle risorse all'ultimo momento, come le cose stanno chiudendo ed eccitante. Per analogia, è il "finalmente" di una prova/eccetto, mentre quello che vuoi è il "else" di una prova/eccetto.

Il modo più semplice che posso pensare continua a creare un flag globale, che si imposta solo quando lo script "ha successo" ... e poi avere tutte le funzioni si allegano al atexit assegno quella bandiera, e non fare nulla a meno che non sia stato impostato.

Esempio:

_success = False 
def atsuccess(func, *args, **kwds): 
    def wrapper(): 
     if _success: 
      func(*args,**kwds) 
    atexit(wrapper) 

def set_success(): 
    global _success 
    _success = True 

# then call atsuccess() to attach your callbacks, 
# and call set_success() before your script returns 

Una limitazione è che se avete qualsiasi codice che chiama sys.exit(0) prima di impostare il flag successo. Tale codice dovrebbe (probabilmente) essere refactored per ritornare prima alla funzione principale, in modo che si chiami set_success e sys.exit in un unico posto. In mancanza di questo, avrete bisogno di aggiungere qualcosa come il seguente wrapper per il punto di ingresso principale nello script:

try: 
    main() 
except SystemExit, err: 
    if err.code == 0: 
     set_success() 
    raise 
+0

Questo è probabilmente il modo più semplice per ottenere ciò che ho chiesto. –

4

avvolgere il corpo del vostro programma in una dichiarazione with e definire un oggetto di contesto corrispondente che esegue solo la vostra azione quando non sono state sollevate eccezioni. Qualcosa di simile:

class AtExit(object): 
    def __enter__(self): 
     return self 

    def __exit__(self, exc_type, exc_value, traceback): 
     if exc_value is None: 
      print "Success!" 
     else: 
      print "Failure!" 

if __name__ == "__main__": 
     with AtExit(): 
      print "Running" 
#   raise Exception("Error") 
+0

Questo è un buon modo generale di fare le cose all'uscita da una parte del programma, non solo alla fine dell'intero programma. È uno schema utile, quindi +1. –

Problemi correlati