--- /dev/null
+"""\r
+atexit.py - allow programmer to define multiple exit functions to be executed\r
+upon normal program termination.\r
+\r
+One public function, register, is defined.\r
+"""\r
+\r
+__all__ = ["register"]\r
+\r
+import sys\r
+\r
+_exithandlers = []\r
+def _run_exitfuncs():\r
+ """run any registered exit functions\r
+\r
+ _exithandlers is traversed in reverse order so functions are executed\r
+ last in, first out.\r
+ """\r
+\r
+ exc_info = None\r
+ while _exithandlers:\r
+ func, targs, kargs = _exithandlers.pop()\r
+ try:\r
+ func(*targs, **kargs)\r
+ except SystemExit:\r
+ exc_info = sys.exc_info()\r
+ except:\r
+ import traceback\r
+ print >> sys.stderr, "Error in atexit._run_exitfuncs:"\r
+ traceback.print_exc()\r
+ exc_info = sys.exc_info()\r
+\r
+ if exc_info is not None:\r
+ raise exc_info[0], exc_info[1], exc_info[2]\r
+\r
+\r
+def register(func, *targs, **kargs):\r
+ """register a function to be executed upon normal program termination\r
+\r
+ func - function to be called at exit\r
+ targs - optional arguments to pass to func\r
+ kargs - optional keyword arguments to pass to func\r
+\r
+ func is returned to facilitate usage as a decorator.\r
+ """\r
+ _exithandlers.append((func, targs, kargs))\r
+ return func\r
+\r
+if hasattr(sys, "exitfunc"):\r
+ # Assume it's another registered exit function - append it to our list\r
+ register(sys.exitfunc)\r
+sys.exitfunc = _run_exitfuncs\r
+\r
+if __name__ == "__main__":\r
+ def x1():\r
+ print "running x1"\r
+ def x2(n):\r
+ print "running x2(%r)" % (n,)\r
+ def x3(n, kwd=None):\r
+ print "running x3(%r, kwd=%r)" % (n, kwd)\r
+\r
+ register(x1)\r
+ register(x2, 12)\r
+ register(x3, 5, "bar")\r
+ register(x3, "no kwd args")\r