diff -Naur src.orig/Doc/lib/libatexit.tex src/Doc/lib/libatexit.tex --- src.orig/Doc/lib/libatexit.tex Wed Dec 31 18:00:00 1969 +++ src/Doc/lib/libatexit.tex Fri Jun 23 17:26:23 2000 @@ -0,0 +1,45 @@ +\section{\module{atexit} --- + exit handlers} + +\declaremodule{standard}{atexit} +\sectionauthor{Skip Montanaro}{skip@mojam.com} +\modulesynopsis{Register and execute cleanup functions.} + +The \module{atexit} module defines a single function to register cleanup +functions. Functions thus registered are automatically executed upon normal +interpreter termination. + +\begin{funcdesc}{register}{func\optional{, *args\optional{, **kargs}}} +Register \code{func} as a function to be executed at termination. Any +optional arguments that are to be passed to func must be passed as arguments +to \func{register}. + +At normal program termination (for instance, if \func{sys.exit} is called or +the main module's execution completes), all functions registered are called +in last in, first out order. The assumption is that lower level modules +will normally be imported before higher level modules and thus must be +cleaned up later. + +\subsection{Example} + +The following simple example demonstrates how a module can initialize a +counter from a file when it is imported and save the counter's updated value +automatically when the program terminates. + +\begin{verbatim} +try: + _count = eval(open("/tmp/counter").read()) +except IOError: + _count = 0 + +def incrcounter(n): + global _count + _count = _count + n + +def savecounter(): + open("/tmp/counter", "w").write("%d" % _count) + +import atexit +atexit.register(savecounter) +\end{verbatim} + diff -Naur src.orig/Lib/atexit.py src/Lib/atexit.py --- src.orig/Lib/atexit.py Wed Dec 31 18:00:00 1969 +++ src/Lib/atexit.py Fri Jun 23 17:27:32 2000 @@ -0,0 +1,54 @@ +""" +atexit.py - allow programmer to define multiple exit functions to be executed +upon normal program termination. + +One public function, register, is defined. +""" + +_exithandlers = [] +def _run_exitfuncs(): + """run any registered exit functions + + _exithandlers is traversed in reverse order so functions are executed + last in, first out. + """ + + while _exithandlers: + func, targs, kargs = _exithandlers[-1] + apply(func, targs, kargs) + _exithandlers.remove(_exithandlers[-1]) + +def register(func, *targs, **kargs): + """register a function to be executed upon normal program termination + + func - function to be called at exit + targs - optional arguments to pass to func + kargs - optional keyword arguments to pass to func + """ + _exithandlers.append((func, targs, kargs)) + +import sys +try: + x = sys.exitfunc +except AttributeError: + sys.exitfunc = _run_exitfuncs +else: + # if x isn't our own exit func executive, assume it's another + # registered exit function - append it to our list... + if x != _run_exitfuncs: + register(x) +del sys + +if __name__ == "__main__": + def x1(): + print "running x1" + def x2(n): + print "running x2(%s)" % `n` + def x3(n, kwd=None): + print "running x3(%s, kwd=%s)" % (`n`, `kwd`) + + register(x1) + register(x2, 12) + register(x3, 5, "bar") + register(x3, "no kwd args") + diff -Naur src.orig/Lib/test/output/test_atexit src/Lib/test/output/test_atexit --- src.orig/Lib/test/output/test_atexit Wed Dec 31 18:00:00 1969 +++ src/Lib/test/output/test_atexit Fri Jun 23 17:28:53 2000 @@ -0,0 +1,4 @@ +test_atexit +handler2 (7,) {'kw': 'abc'} +handler2 () {} +handler1 diff -Naur src.orig/Lib/test/test_atexit.py src/Lib/test/test_atexit.py --- src.orig/Lib/test/test_atexit.py Wed Dec 31 18:00:00 1969 +++ src/Lib/test/test_atexit.py Fri Jun 23 17:28:31 2000 @@ -0,0 +1,24 @@ +# Test the exit module +from test_support import verbose +import atexit + +def handler1(): + print "handler1" + +def handler2(*args, **kargs): + print "handler2", args, kargs + +# save any exit functions that may have been registered as part of the +# test framework +_exithandlers = atexit._exithandlers +atexit._exithandlers = [] + +atexit.register(handler1) +atexit.register(handler2) +atexit.register(handler2, 7, kw="abc") + +# simulate exit behavior by calling atexit._run_exitfuncs directly... +atexit._run_exitfuncs() + +# restore exit handlers +atexit._exithandlers = _exithandlers