|
1 """ |
|
2 atexit.py - allow programmer to define multiple exit functions to be executed |
|
3 upon normal program termination. |
|
4 |
|
5 One public function, register, is defined. |
|
6 """ |
|
7 |
|
8 __all__ = ["register"] |
|
9 |
|
10 import sys |
|
11 |
|
12 _exithandlers = [] |
|
13 def _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 |
|
37 def 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 |
|
49 if hasattr(sys, "exitfunc"): |
|
50 # Assume it's another registered exit function - append it to our list |
|
51 register(sys.exitfunc) |
|
52 sys.exitfunc = _run_exitfuncs |
|
53 |
|
54 if __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") |