summaryrefslogtreecommitdiff
path: root/devdocs/python~3.12/library%2Fatexit.html
blob: 982040cf0eb77c0055815144fd6c7612f937aa22 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
 <span id="atexit-exit-handlers"></span><h1>atexit — Exit handlers</h1>  <p>The <a class="reference internal" href="#module-atexit" title="atexit: Register and execute cleanup functions."><code>atexit</code></a> module defines functions to register and unregister cleanup functions. Functions thus registered are automatically executed upon normal interpreter termination. <a class="reference internal" href="#module-atexit" title="atexit: Register and execute cleanup functions."><code>atexit</code></a> runs these functions in the <em>reverse</em> order in which they were registered; if you register <code>A</code>, <code>B</code>, and <code>C</code>, at interpreter termination time they will be run in the order <code>C</code>, <code>B</code>, <code>A</code>.</p> <p><strong>Note:</strong> The functions registered via this module are not called when the program is killed by a signal not handled by Python, when a Python fatal internal error is detected, or when <a class="reference internal" href="os#os._exit" title="os._exit"><code>os._exit()</code></a> is called.</p> <p><strong>Note:</strong> The effect of registering or unregistering functions from within a cleanup function is undefined.</p> <div class="versionchanged"> <p><span class="versionmodified changed">Changed in version 3.7: </span>When used with C-API subinterpreters, registered functions are local to the interpreter they were registered in.</p> </div> <dl class="py function"> <dt class="sig sig-object py" id="atexit.register">
<code>atexit.register(func, *args, **kwargs)</code> </dt> <dd>
<p>Register <em>func</em> as a function to be executed at termination. Any optional arguments that are to be passed to <em>func</em> must be passed as arguments to <a class="reference internal" href="#atexit.register" title="atexit.register"><code>register()</code></a>. It is possible to register the same function and arguments more than once.</p> <p>At normal program termination (for instance, if <a class="reference internal" href="sys#sys.exit" title="sys.exit"><code>sys.exit()</code></a> 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.</p> <p>If an exception is raised during execution of the exit handlers, a traceback is printed (unless <a class="reference internal" href="exceptions#SystemExit" title="SystemExit"><code>SystemExit</code></a> is raised) and the exception information is saved. After all exit handlers have had a chance to run, the last exception to be raised is re-raised.</p> <p>This function returns <em>func</em>, which makes it possible to use it as a decorator.</p> <div class="admonition warning"> <p class="admonition-title">Warning</p> <p>Starting new threads or calling <a class="reference internal" href="os#os.fork" title="os.fork"><code>os.fork()</code></a> from a registered function can lead to race condition between the main Python runtime thread freeing thread states while internal <a class="reference internal" href="threading#module-threading" title="threading: Thread-based parallelism."><code>threading</code></a> routines or the new process try to use that state. This can lead to crashes rather than clean shutdown.</p> </div> <div class="versionchanged"> <p><span class="versionmodified changed">Changed in version 3.12: </span>Attempts to start a new thread or <a class="reference internal" href="os#os.fork" title="os.fork"><code>os.fork()</code></a> a new process in a registered function now leads to <a class="reference internal" href="exceptions#RuntimeError" title="RuntimeError"><code>RuntimeError</code></a>.</p> </div> </dd>
</dl> <dl class="py function"> <dt class="sig sig-object py" id="atexit.unregister">
<code>atexit.unregister(func)</code> </dt> <dd>
<p>Remove <em>func</em> from the list of functions to be run at interpreter shutdown. <a class="reference internal" href="#atexit.unregister" title="atexit.unregister"><code>unregister()</code></a> silently does nothing if <em>func</em> was not previously registered. If <em>func</em> has been registered more than once, every occurrence of that function in the <a class="reference internal" href="#module-atexit" title="atexit: Register and execute cleanup functions."><code>atexit</code></a> call stack will be removed. Equality comparisons (<code>==</code>) are used internally during unregistration, so function references do not need to have matching identities.</p> </dd>
</dl> <div class="admonition seealso"> <p class="admonition-title">See also</p> <dl class="simple"> <dt>
<code>Module</code> <a class="reference internal" href="readline#module-readline" title="readline: GNU readline support for Python. (Unix)"><code>readline</code></a>
</dt>
<dd>
<p>Useful example of <a class="reference internal" href="#module-atexit" title="atexit: Register and execute cleanup functions."><code>atexit</code></a> to read and write <a class="reference internal" href="readline#module-readline" title="readline: GNU readline support for Python. (Unix)"><code>readline</code></a> history files.</p> </dd> </dl> </div> <section id="atexit-example"> <span id="id1"></span><h2>atexit Example</h2> <p>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 without relying on the application making an explicit call into this module at termination.</p> <pre data-language="python">try:
    with open('counterfile') as infile:
        _count = int(infile.read())
except FileNotFoundError:
    _count = 0

def incrcounter(n):
    global _count
    _count = _count + n

def savecounter():
    with open('counterfile', 'w') as outfile:
        outfile.write('%d' % _count)

import atexit

atexit.register(savecounter)
</pre> <p>Positional and keyword arguments may also be passed to <a class="reference internal" href="#atexit.register" title="atexit.register"><code>register()</code></a> to be passed along to the registered function when it is called:</p> <pre data-language="python">def goodbye(name, adjective):
    print('Goodbye %s, it was %s to meet you.' % (name, adjective))

import atexit

atexit.register(goodbye, 'Donny', 'nice')
# or:
atexit.register(goodbye, adjective='nice', name='Donny')
</pre> <p>Usage as a <a class="reference internal" href="../glossary#term-decorator"><span class="xref std std-term">decorator</span></a>:</p> <pre data-language="python">import atexit

@atexit.register
def goodbye():
    print('You are now leaving the Python sector.')
</pre> <p>This only works with functions that can be called without arguments.</p> </section> <div class="_attribution">
  <p class="_attribution-p">
    &copy; 2001&ndash;2023 Python Software Foundation<br>Licensed under the PSF License.<br>
    <a href="https://docs.python.org/3.12/library/atexit.html" class="_attribution-link">https://docs.python.org/3.12/library/atexit.html</a>
  </p>
</div>