[code.view]

[top] / python / PyMOTW / docs / atexit / index.html


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>atexit – Call functions when a program is closing down &mdash; Python Module of the Week</title>
    <link rel="stylesheet" href="../_static/sphinxdoc.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '../',
        VERSION:     '1.132',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>
    <script type="text/javascript" src="../_static/jquery.js"></script>
    <script type="text/javascript" src="../_static/underscore.js"></script>
    <script type="text/javascript" src="../_static/doctools.js"></script>
    <link rel="author" title="About these documents" href="../about.html" />
    <link rel="top" title="Python Module of the Week" href="../index.html" />
    <link rel="up" title="Python Runtime Services" href="../runtime_services.html" />
    <link rel="next" title="contextlib – Context manager utilities" href="../contextlib/index.html" />
    <link rel="prev" title="abc – Abstract Base Classes" href="../abc/index.html" /> 
  </head>
  <body>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="../contextlib/index.html" title="contextlib – Context manager utilities"
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="../abc/index.html" title="abc – Abstract Base Classes"
             accesskey="P">previous</a> |</li>
        <li><a href="../contents.html">PyMOTW</a> &raquo;</li>
          <li><a href="../runtime_services.html" accesskey="U">Python Runtime Services</a> &raquo;</li> 
      </ul>
    </div>
      <div class="sphinxsidebar">
        <div class="sphinxsidebarwrapper">
  <h3><a href="../contents.html">Table Of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">atexit &#8211; Call functions when a program is closing down</a><ul>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#when-are-atexit-functions-not-called">When are atexit functions not called?</a></li>
<li><a class="reference internal" href="#exceptions-in-atexit-callbacks">Exceptions in atexit Callbacks</a></li>
</ul>
</li>
</ul>

  <h4>Previous topic</h4>
  <p class="topless"><a href="../abc/index.html"
                        title="previous chapter">abc &#8211; Abstract Base Classes</a></p>
  <h4>Next topic</h4>
  <p class="topless"><a href="../contextlib/index.html"
                        title="next chapter">contextlib &#8211; Context manager utilities</a></p>
  <h3>This Page</h3>
  <ul class="this-page-menu">
    <li><a href="../_sources/atexit/index.txt"
           rel="nofollow">Show Source</a></li>
  </ul>
<div id="searchbox" style="display: none">
  <h3>Quick search</h3>
    <form class="search" action="../search.html" method="get">
      <input type="text" name="q" size="18" />
      <input type="submit" value="Go" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    <p class="searchtip" style="font-size: 90%">
    Enter search terms or a module, class or function name.
    </p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body">
            
  <div class="section" id="module-atexit">
<span id="atexit-call-functions-when-a-program-is-closing-down"></span><h1>atexit &#8211; Call functions when a program is closing down<a class="headerlink" href="#module-atexit" title="Permalink to this headline">¶</a></h1>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Purpose:</th><td class="field-body">Register function(s) to be called when a program is closing down.</td>
</tr>
<tr class="field"><th class="field-name">Python Version:</th><td class="field-body">2.1.3 and later</td>
</tr>
</tbody>
</table>
<p>The atexit module provides a simple interface to register functions to be
called when a program closes down normally. The sys module also provides a
hook, sys.exitfunc, but only one function can be registered there. The atexit
registry can be used by multiple modules and libraries simultaneously.</p>
<div class="section" id="examples">
<h2>Examples<a class="headerlink" href="#examples" title="Permalink to this headline">¶</a></h2>
<p>A simple example of registering a function via atexit.register() looks like:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">atexit</span>

<span class="k">def</span> <span class="nf">all_done</span><span class="p">():</span>
    <span class="k">print</span> <span class="s">&#39;all_done()&#39;</span>

<span class="k">print</span> <span class="s">&#39;Registering&#39;</span>
<span class="n">atexit</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">all_done</span><span class="p">)</span>
<span class="k">print</span> <span class="s">&#39;Registered&#39;</span>
</pre></div>
</div>
<p>Since the program doesn&#8217;t do anything else, all_done() is called right away:</p>
<div class="highlight-python"><pre>$ python atexit_simple.py

Registering
Registered
all_done()</pre>
</div>
<p>It is also possible to register more than one function, and to pass arguments.
That can be useful to cleanly disconnect from databases, remove temporary
files, etc. Since it is possible to pass arguments to the registered
functions, we don&#8217;t even need to keep a separate list of things to clean up &#8211;
we can just register a clean up function more than once.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">atexit</span>

<span class="k">def</span> <span class="nf">my_cleanup</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
    <span class="k">print</span> <span class="s">&#39;my_cleanup(</span><span class="si">%s</span><span class="s">)&#39;</span> <span class="o">%</span> <span class="n">name</span>

<span class="n">atexit</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">my_cleanup</span><span class="p">,</span> <span class="s">&#39;first&#39;</span><span class="p">)</span>
<span class="n">atexit</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">my_cleanup</span><span class="p">,</span> <span class="s">&#39;second&#39;</span><span class="p">)</span>
<span class="n">atexit</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">my_cleanup</span><span class="p">,</span> <span class="s">&#39;third&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>Notice that order in which the exit functions are called is the reverse of
the order they are registered. This allows modules to be cleaned up in the
reverse order from which they are imported (and therefore register their
atexit functions), which should reduce dependency conflicts.</p>
<div class="highlight-python"><pre>$ python atexit_multiple.py

my_cleanup(third)
my_cleanup(second)
my_cleanup(first)</pre>
</div>
</div>
<div class="section" id="when-are-atexit-functions-not-called">
<h2>When are atexit functions not called?<a class="headerlink" href="#when-are-atexit-functions-not-called" title="Permalink to this headline">¶</a></h2>
<p>The callbacks registered with atexit are not invoked if:</p>
<ul class="simple">
<li>the program dies because of a signal</li>
<li>os._exit() is invoked directly</li>
<li>a Python fatal error is detected (in the interpreter)</li>
</ul>
<p>To illustrate a program being killed via a signal, we can modify one
of the examples from the <a class="reference internal" href="../subprocess/index.html#module-subprocess" title="subprocess: Work with additional processes"><tt class="xref py py-mod docutils literal"><span class="pre">subprocess</span></tt></a> article. There are 2 files
involved, the parent and the child programs. The parent starts the
child, pauses, then kills it:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">signal</span>
<span class="kn">import</span> <span class="nn">subprocess</span>
<span class="kn">import</span> <span class="nn">time</span>

<span class="n">proc</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="s">&#39;atexit_signal_child.py&#39;</span><span class="p">)</span>
<span class="k">print</span> <span class="s">&#39;PARENT: Pausing before sending signal...&#39;</span>
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">print</span> <span class="s">&#39;PARENT: Signaling child&#39;</span>
<span class="n">os</span><span class="o">.</span><span class="n">kill</span><span class="p">(</span><span class="n">proc</span><span class="o">.</span><span class="n">pid</span><span class="p">,</span> <span class="n">signal</span><span class="o">.</span><span class="n">SIGTERM</span><span class="p">)</span>
</pre></div>
</div>
<p>The child sets up an atexit callback, to prove that it is not called.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">atexit</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="kn">import</span> <span class="nn">sys</span>

<span class="k">def</span> <span class="nf">not_called</span><span class="p">():</span>
    <span class="k">print</span> <span class="s">&#39;CHILD: atexit handler should not have been called&#39;</span>

<span class="k">print</span> <span class="s">&#39;CHILD: Registering atexit handler&#39;</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span>
<span class="n">atexit</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">not_called</span><span class="p">)</span>

<span class="k">print</span> <span class="s">&#39;CHILD: Pausing to wait for signal&#39;</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span>
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
</pre></div>
</div>
<p>When run, the output should look something like this:</p>
<div class="highlight-python"><pre>$ python atexit_signal_parent.py

CHILD: Registering atexit handler
CHILD: Pausing to wait for signal
PARENT: Pausing before sending signal...
PARENT: Signaling child</pre>
</div>
<p>Note that the child does not print the message embedded in not_called().</p>
<p>Similarly, if a program bypasses the normal exit path it can avoid having the
atexit callbacks invoked.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">atexit</span>
<span class="kn">import</span> <span class="nn">os</span>

<span class="k">def</span> <span class="nf">not_called</span><span class="p">():</span>
    <span class="k">print</span> <span class="s">&#39;This should not be called&#39;</span>

<span class="k">print</span> <span class="s">&#39;Registering&#39;</span>
<span class="n">atexit</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">not_called</span><span class="p">)</span>
<span class="k">print</span> <span class="s">&#39;Registered&#39;</span>

<span class="k">print</span> <span class="s">&#39;Exiting...&#39;</span>
<span class="n">os</span><span class="o">.</span><span class="n">_exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
</pre></div>
</div>
<p>Since we call os._exit() instead of exiting normally, the callback is not
invoked.</p>
<div class="highlight-python"><pre>$ python atexit_os_exit.py</pre>
</div>
<p>If we had instead used sys.exit(), the callbacks would still have been called.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">atexit</span>
<span class="kn">import</span> <span class="nn">sys</span>

<span class="k">def</span> <span class="nf">all_done</span><span class="p">():</span>
    <span class="k">print</span> <span class="s">&#39;all_done()&#39;</span>

<span class="k">print</span> <span class="s">&#39;Registering&#39;</span>
<span class="n">atexit</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">all_done</span><span class="p">)</span>
<span class="k">print</span> <span class="s">&#39;Registered&#39;</span>

<span class="k">print</span> <span class="s">&#39;Exiting...&#39;</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">()</span>
</pre></div>
</div>
<div class="highlight-python"><pre>$ python atexit_sys_exit.py

Registering
Registered
Exiting...
all_done()</pre>
</div>
<p>Simulating a fatal error in the Python interpreter is left as an exercise to
the reader.</p>
</div>
<div class="section" id="exceptions-in-atexit-callbacks">
<h2>Exceptions in atexit Callbacks<a class="headerlink" href="#exceptions-in-atexit-callbacks" title="Permalink to this headline">¶</a></h2>
<p>Tracebacks for exceptions raised in atexit callbacks are printed to the
console and the last exception raised is re-raised to be the final error
message of the program.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">atexit</span>

<span class="k">def</span> <span class="nf">exit_with_exception</span><span class="p">(</span><span class="n">message</span><span class="p">):</span>
    <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>

<span class="n">atexit</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">exit_with_exception</span><span class="p">,</span> <span class="s">&#39;Registered first&#39;</span><span class="p">)</span>
<span class="n">atexit</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">exit_with_exception</span><span class="p">,</span> <span class="s">&#39;Registered second&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>Notice again that the registration order controls the execution order. If an
error in one callback introduces an error in another (registered earlier, but
called later), the final error message might not be the most useful error
message to show the user.</p>
<div class="highlight-python"><pre>$ python atexit_exception.py

Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "atexit_exception.py", line 37, in exit_with_exception
    raise RuntimeError(message)
RuntimeError: Registered second
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "atexit_exception.py", line 37, in exit_with_exception
    raise RuntimeError(message)
RuntimeError: Registered first
Error in sys.exitfunc:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "atexit_exception.py", line 37, in exit_with_exception
    raise RuntimeError(message)
RuntimeError: Registered first</pre>
</div>
<p>In general you will probably want to handle and quietly log all exceptions in
your cleanup functions, since it is messy to have a program dump errors on
exit.</p>
<div class="admonition-see-also admonition seealso">
<p class="first admonition-title">See also</p>
<dl class="last docutils">
<dt><a class="reference external" href="http://docs.python.org/library/atexit.html">atexit</a></dt>
<dd>The standard library documentation for this module.</dd>
</dl>
</div>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="../contextlib/index.html" title="contextlib – Context manager utilities"
             >next</a> |</li>
        <li class="right" >
          <a href="../abc/index.html" title="abc – Abstract Base Classes"
             >previous</a> |</li>
        <li><a href="../contents.html">PyMOTW</a> &raquo;</li>
          <li><a href="../runtime_services.html" >Python Runtime Services</a> &raquo;</li> 
      </ul>
    </div>
    <div class="footer">
      &copy; Copyright Doug Hellmann.
      Last updated on Oct 24, 2010.
      Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.

    <br/><a href="http://creativecommons.org/licenses/by-nc-sa/3.0/us/" rel="license"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-nc-sa/3.0/us/88x31.png"/></a>
    
    </div>
  </body>
</html>

[top] / python / PyMOTW / docs / atexit / index.html

contact | logmethods.com