1""" 2atexit.py - allow programmer to define multiple exit functions to be executed 3upon normal program termination. 4 5One public function, register, is defined. 6""" 7 8__all__ = ["register"] 9 10import sys 11 12_exithandlers = [] 13def _run_exitfuncs(): 14 """run any registered exit functions 15 16 _exithandlers is traversed in reverse order so functions are executed 17 last in, first out. 18 """ 19 20 exc_info = None 21 while _exithandlers: 22 func, targs, kargs = _exithandlers.pop() 23 try: 24 func(*targs, **kargs) 25 except SystemExit: 26 exc_info = sys.exc_info() 27 except: 28 import traceback 29 print >> sys.stderr, "Error in atexit._run_exitfuncs:" 30 traceback.print_exc() 31 exc_info = sys.exc_info() 32 33 if exc_info is not None: 34 raise exc_info[0], exc_info[1], exc_info[2] 35 36 37def register(func, *targs, **kargs): 38 """register a function to be executed upon normal program termination 39 40 func - function to be called at exit 41 targs - optional arguments to pass to func 42 kargs - optional keyword arguments to pass to func 43 44 func is returned to facilitate usage as a decorator. 45 """ 46 _exithandlers.append((func, targs, kargs)) 47 return func 48 49if hasattr(sys, "exitfunc"): 50 # Assume it's another registered exit function - append it to our list 51 register(sys.exitfunc) 52sys.exitfunc = _run_exitfuncs 53 54if __name__ == "__main__": 55 def x1(): 56 print "running x1" 57 def x2(n): 58 print "running x2(%r)" % (n,) 59 def x3(n, kwd=None): 60 print "running x3(%r, kwd=%r)" % (n, kwd) 61 62 register(x1) 63 register(x2, 12) 64 register(x3, 5, "bar") 65 register(x3, "no kwd args") 66