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