1053 lines
98 KiB
HTML
1053 lines
98 KiB
HTML
|
|
|||
|
<!DOCTYPE html>
|
|||
|
|
|||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|||
|
<head>
|
|||
|
<meta charset="utf-8" />
|
|||
|
<title>contextlib — Utilities for with-statement contexts — Python 3.7.4 documentation</title>
|
|||
|
<link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
|
|||
|
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
|||
|
|
|||
|
<script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></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>
|
|||
|
<script type="text/javascript" src="../_static/language_data.js"></script>
|
|||
|
|
|||
|
<script type="text/javascript" src="../_static/sidebar.js"></script>
|
|||
|
|
|||
|
<link rel="search" type="application/opensearchdescription+xml"
|
|||
|
title="Search within Python 3.7.4 documentation"
|
|||
|
href="../_static/opensearch.xml"/>
|
|||
|
<link rel="author" title="About these documents" href="../about.html" />
|
|||
|
<link rel="index" title="Index" href="../genindex.html" />
|
|||
|
<link rel="search" title="Search" href="../search.html" />
|
|||
|
<link rel="copyright" title="Copyright" href="../copyright.html" />
|
|||
|
<link rel="next" title="abc — Abstract Base Classes" href="abc.html" />
|
|||
|
<link rel="prev" title="dataclasses — Data Classes" href="dataclasses.html" />
|
|||
|
<link rel="shortcut icon" type="image/png" href="../_static/py.png" />
|
|||
|
<link rel="canonical" href="https://docs.python.org/3/library/contextlib.html" />
|
|||
|
|
|||
|
<script type="text/javascript" src="../_static/copybutton.js"></script>
|
|||
|
<script type="text/javascript" src="../_static/switchers.js"></script>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<style>
|
|||
|
@media only screen {
|
|||
|
table.full-width-table {
|
|||
|
width: 100%;
|
|||
|
}
|
|||
|
}
|
|||
|
</style>
|
|||
|
|
|||
|
|
|||
|
</head><body>
|
|||
|
|
|||
|
<div class="related" role="navigation" aria-label="related navigation">
|
|||
|
<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="abc.html" title="abc — Abstract Base Classes"
|
|||
|
accesskey="N">next</a> |</li>
|
|||
|
<li class="right" >
|
|||
|
<a href="dataclasses.html" title="dataclasses — Data Classes"
|
|||
|
accesskey="P">previous</a> |</li>
|
|||
|
<li><img src="../_static/py.png" alt=""
|
|||
|
style="vertical-align: middle; margin-top: -1px"/></li>
|
|||
|
<li><a href="https://www.python.org/">Python</a> »</li>
|
|||
|
<li>
|
|||
|
<span class="language_switcher_placeholder">en</span>
|
|||
|
<span class="version_switcher_placeholder">3.7.4</span>
|
|||
|
<a href="../index.html">Documentation </a> »
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> »</li>
|
|||
|
<li class="nav-item nav-item-2"><a href="python.html" accesskey="U">Python Runtime Services</a> »</li>
|
|||
|
<li class="right">
|
|||
|
|
|||
|
|
|||
|
<div class="inline-search" style="display: none" role="search">
|
|||
|
<form class="inline-search" action="../search.html" method="get">
|
|||
|
<input placeholder="Quick search" type="text" name="q" />
|
|||
|
<input type="submit" value="Go" />
|
|||
|
<input type="hidden" name="check_keywords" value="yes" />
|
|||
|
<input type="hidden" name="area" value="default" />
|
|||
|
</form>
|
|||
|
</div>
|
|||
|
<script type="text/javascript">$('.inline-search').show(0);</script>
|
|||
|
|
|
|||
|
</li>
|
|||
|
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
|
|||
|
<div class="document">
|
|||
|
<div class="documentwrapper">
|
|||
|
<div class="bodywrapper">
|
|||
|
<div class="body" role="main">
|
|||
|
|
|||
|
<div class="section" id="module-contextlib">
|
|||
|
<span id="contextlib-utilities-for-with-statement-contexts"></span><h1><code class="xref py py-mod docutils literal notranslate"><span class="pre">contextlib</span></code> — Utilities for <code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code>-statement contexts<a class="headerlink" href="#module-contextlib" title="Permalink to this headline">¶</a></h1>
|
|||
|
<p><strong>Source code:</strong> <a class="reference external" href="https://github.com/python/cpython/tree/3.7/Lib/contextlib.py">Lib/contextlib.py</a></p>
|
|||
|
<hr class="docutils" />
|
|||
|
<p>This module provides utilities for common tasks involving the <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a>
|
|||
|
statement. For more information see also <a class="reference internal" href="stdtypes.html#typecontextmanager"><span class="std std-ref">Context Manager Types</span></a> and
|
|||
|
<a class="reference internal" href="../reference/datamodel.html#context-managers"><span class="std std-ref">With Statement Context Managers</span></a>.</p>
|
|||
|
<div class="section" id="utilities">
|
|||
|
<h2>Utilities<a class="headerlink" href="#utilities" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>Functions and classes provided:</p>
|
|||
|
<dl class="class">
|
|||
|
<dt id="contextlib.AbstractContextManager">
|
|||
|
<em class="property">class </em><code class="descclassname">contextlib.</code><code class="descname">AbstractContextManager</code><a class="headerlink" href="#contextlib.AbstractContextManager" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>An <a class="reference internal" href="../glossary.html#term-abstract-base-class"><span class="xref std std-term">abstract base class</span></a> for classes that implement
|
|||
|
<a class="reference internal" href="../reference/datamodel.html#object.__enter__" title="object.__enter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">object.__enter__()</span></code></a> and <a class="reference internal" href="../reference/datamodel.html#object.__exit__" title="object.__exit__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">object.__exit__()</span></code></a>. A default
|
|||
|
implementation for <a class="reference internal" href="../reference/datamodel.html#object.__enter__" title="object.__enter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">object.__enter__()</span></code></a> is provided which returns
|
|||
|
<code class="docutils literal notranslate"><span class="pre">self</span></code> while <a class="reference internal" href="../reference/datamodel.html#object.__exit__" title="object.__exit__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">object.__exit__()</span></code></a> is an abstract method which by default
|
|||
|
returns <code class="docutils literal notranslate"><span class="pre">None</span></code>. See also the definition of <a class="reference internal" href="stdtypes.html#typecontextmanager"><span class="std std-ref">Context Manager Types</span></a>.</p>
|
|||
|
<div class="versionadded">
|
|||
|
<p><span class="versionmodified added">New in version 3.6.</span></p>
|
|||
|
</div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<dl class="class">
|
|||
|
<dt id="contextlib.AbstractAsyncContextManager">
|
|||
|
<em class="property">class </em><code class="descclassname">contextlib.</code><code class="descname">AbstractAsyncContextManager</code><a class="headerlink" href="#contextlib.AbstractAsyncContextManager" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>An <a class="reference internal" href="../glossary.html#term-abstract-base-class"><span class="xref std std-term">abstract base class</span></a> for classes that implement
|
|||
|
<a class="reference internal" href="../reference/datamodel.html#object.__aenter__" title="object.__aenter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">object.__aenter__()</span></code></a> and <a class="reference internal" href="../reference/datamodel.html#object.__aexit__" title="object.__aexit__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">object.__aexit__()</span></code></a>. A default
|
|||
|
implementation for <a class="reference internal" href="../reference/datamodel.html#object.__aenter__" title="object.__aenter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">object.__aenter__()</span></code></a> is provided which returns
|
|||
|
<code class="docutils literal notranslate"><span class="pre">self</span></code> while <a class="reference internal" href="../reference/datamodel.html#object.__aexit__" title="object.__aexit__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">object.__aexit__()</span></code></a> is an abstract method which by default
|
|||
|
returns <code class="docutils literal notranslate"><span class="pre">None</span></code>. See also the definition of
|
|||
|
<a class="reference internal" href="../reference/datamodel.html#async-context-managers"><span class="std std-ref">Asynchronous Context Managers</span></a>.</p>
|
|||
|
<div class="versionadded">
|
|||
|
<p><span class="versionmodified added">New in version 3.7.</span></p>
|
|||
|
</div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<dl class="function">
|
|||
|
<dt id="contextlib.contextmanager">
|
|||
|
<code class="descclassname">@</code><code class="descclassname">contextlib.</code><code class="descname">contextmanager</code><a class="headerlink" href="#contextlib.contextmanager" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>This function is a <a class="reference internal" href="../glossary.html#term-decorator"><span class="xref std std-term">decorator</span></a> that can be used to define a factory
|
|||
|
function for <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> statement context managers, without needing to
|
|||
|
create a class or separate <a class="reference internal" href="../reference/datamodel.html#object.__enter__" title="object.__enter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__enter__()</span></code></a> and <a class="reference internal" href="../reference/datamodel.html#object.__exit__" title="object.__exit__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__exit__()</span></code></a> methods.</p>
|
|||
|
<p>While many objects natively support use in with statements, sometimes a
|
|||
|
resource needs to be managed that isn’t a context manager in its own right,
|
|||
|
and doesn’t implement a <code class="docutils literal notranslate"><span class="pre">close()</span></code> method for use with <code class="docutils literal notranslate"><span class="pre">contextlib.closing</span></code></p>
|
|||
|
<p>An abstract example would be the following to ensure correct resource
|
|||
|
management:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">contextlib</span> <span class="k">import</span> <span class="n">contextmanager</span>
|
|||
|
|
|||
|
<span class="nd">@contextmanager</span>
|
|||
|
<span class="k">def</span> <span class="nf">managed_resource</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwds</span><span class="p">):</span>
|
|||
|
<span class="c1"># Code to acquire resource, e.g.:</span>
|
|||
|
<span class="n">resource</span> <span class="o">=</span> <span class="n">acquire_resource</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwds</span><span class="p">)</span>
|
|||
|
<span class="k">try</span><span class="p">:</span>
|
|||
|
<span class="k">yield</span> <span class="n">resource</span>
|
|||
|
<span class="k">finally</span><span class="p">:</span>
|
|||
|
<span class="c1"># Code to release resource, e.g.:</span>
|
|||
|
<span class="n">release_resource</span><span class="p">(</span><span class="n">resource</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="o">>>></span> <span class="k">with</span> <span class="n">managed_resource</span><span class="p">(</span><span class="n">timeout</span><span class="o">=</span><span class="mi">3600</span><span class="p">)</span> <span class="k">as</span> <span class="n">resource</span><span class="p">:</span>
|
|||
|
<span class="o">...</span> <span class="c1"># Resource is released at the end of this block,</span>
|
|||
|
<span class="o">...</span> <span class="c1"># even if code in the block raises an exception</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>The function being decorated must return a <a class="reference internal" href="../glossary.html#term-generator"><span class="xref std std-term">generator</span></a>-iterator when
|
|||
|
called. This iterator must yield exactly one value, which will be bound to
|
|||
|
the targets in the <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> statement’s <code class="xref std std-keyword docutils literal notranslate"><span class="pre">as</span></code> clause, if any.</p>
|
|||
|
<p>At the point where the generator yields, the block nested in the <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a>
|
|||
|
statement is executed. The generator is then resumed after the block is exited.
|
|||
|
If an unhandled exception occurs in the block, it is reraised inside the
|
|||
|
generator at the point where the yield occurred. Thus, you can use a
|
|||
|
<a class="reference internal" href="../reference/compound_stmts.html#try"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">try</span></code></a>…<a class="reference internal" href="../reference/compound_stmts.html#except"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">except</span></code></a>…<a class="reference internal" href="../reference/compound_stmts.html#finally"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">finally</span></code></a> statement to trap
|
|||
|
the error (if any), or ensure that some cleanup takes place. If an exception is
|
|||
|
trapped merely in order to log it or to perform some action (rather than to
|
|||
|
suppress it entirely), the generator must reraise that exception. Otherwise the
|
|||
|
generator context manager will indicate to the <code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code> statement that
|
|||
|
the exception has been handled, and execution will resume with the statement
|
|||
|
immediately following the <code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code> statement.</p>
|
|||
|
<p><a class="reference internal" href="#contextlib.contextmanager" title="contextlib.contextmanager"><code class="xref py py-func docutils literal notranslate"><span class="pre">contextmanager()</span></code></a> uses <a class="reference internal" href="#contextlib.ContextDecorator" title="contextlib.ContextDecorator"><code class="xref py py-class docutils literal notranslate"><span class="pre">ContextDecorator</span></code></a> so the context managers
|
|||
|
it creates can be used as decorators as well as in <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> statements.
|
|||
|
When used as a decorator, a new generator instance is implicitly created on
|
|||
|
each function call (this allows the otherwise “one-shot” context managers
|
|||
|
created by <a class="reference internal" href="#contextlib.contextmanager" title="contextlib.contextmanager"><code class="xref py py-func docutils literal notranslate"><span class="pre">contextmanager()</span></code></a> to meet the requirement that context
|
|||
|
managers support multiple invocations in order to be used as decorators).</p>
|
|||
|
<div class="versionchanged">
|
|||
|
<p><span class="versionmodified changed">Changed in version 3.2: </span>Use of <a class="reference internal" href="#contextlib.ContextDecorator" title="contextlib.ContextDecorator"><code class="xref py py-class docutils literal notranslate"><span class="pre">ContextDecorator</span></code></a>.</p>
|
|||
|
</div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<dl class="function">
|
|||
|
<dt id="contextlib.asynccontextmanager">
|
|||
|
<code class="descclassname">@</code><code class="descclassname">contextlib.</code><code class="descname">asynccontextmanager</code><a class="headerlink" href="#contextlib.asynccontextmanager" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>Similar to <a class="reference internal" href="#contextlib.contextmanager" title="contextlib.contextmanager"><code class="xref py py-func docutils literal notranslate"><span class="pre">contextmanager()</span></code></a>, but creates an
|
|||
|
<a class="reference internal" href="../reference/datamodel.html#async-context-managers"><span class="std std-ref">asynchronous context manager</span></a>.</p>
|
|||
|
<p>This function is a <a class="reference internal" href="../glossary.html#term-decorator"><span class="xref std std-term">decorator</span></a> that can be used to define a factory
|
|||
|
function for <a class="reference internal" href="../reference/compound_stmts.html#async-with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">async</span> <span class="pre">with</span></code></a> statement asynchronous context managers,
|
|||
|
without needing to create a class or separate <a class="reference internal" href="../reference/datamodel.html#object.__aenter__" title="object.__aenter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__aenter__()</span></code></a> and
|
|||
|
<a class="reference internal" href="../reference/datamodel.html#object.__aexit__" title="object.__aexit__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__aexit__()</span></code></a> methods. It must be applied to an <a class="reference internal" href="../glossary.html#term-asynchronous-generator"><span class="xref std std-term">asynchronous
|
|||
|
generator</span></a> function.</p>
|
|||
|
<p>A simple example:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">contextlib</span> <span class="k">import</span> <span class="n">asynccontextmanager</span>
|
|||
|
|
|||
|
<span class="nd">@asynccontextmanager</span>
|
|||
|
<span class="k">async</span> <span class="k">def</span> <span class="nf">get_connection</span><span class="p">():</span>
|
|||
|
<span class="n">conn</span> <span class="o">=</span> <span class="k">await</span> <span class="n">acquire_db_connection</span><span class="p">()</span>
|
|||
|
<span class="k">try</span><span class="p">:</span>
|
|||
|
<span class="k">yield</span> <span class="n">conn</span>
|
|||
|
<span class="k">finally</span><span class="p">:</span>
|
|||
|
<span class="k">await</span> <span class="n">release_db_connection</span><span class="p">(</span><span class="n">conn</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="k">async</span> <span class="k">def</span> <span class="nf">get_all_users</span><span class="p">():</span>
|
|||
|
<span class="k">async</span> <span class="k">with</span> <span class="n">get_connection</span><span class="p">()</span> <span class="k">as</span> <span class="n">conn</span><span class="p">:</span>
|
|||
|
<span class="k">return</span> <span class="n">conn</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s1">'SELECT ...'</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<div class="versionadded">
|
|||
|
<p><span class="versionmodified added">New in version 3.7.</span></p>
|
|||
|
</div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<dl class="function">
|
|||
|
<dt id="contextlib.closing">
|
|||
|
<code class="descclassname">contextlib.</code><code class="descname">closing</code><span class="sig-paren">(</span><em>thing</em><span class="sig-paren">)</span><a class="headerlink" href="#contextlib.closing" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>Return a context manager that closes <em>thing</em> upon completion of the block. This
|
|||
|
is basically equivalent to:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">contextlib</span> <span class="k">import</span> <span class="n">contextmanager</span>
|
|||
|
|
|||
|
<span class="nd">@contextmanager</span>
|
|||
|
<span class="k">def</span> <span class="nf">closing</span><span class="p">(</span><span class="n">thing</span><span class="p">):</span>
|
|||
|
<span class="k">try</span><span class="p">:</span>
|
|||
|
<span class="k">yield</span> <span class="n">thing</span>
|
|||
|
<span class="k">finally</span><span class="p">:</span>
|
|||
|
<span class="n">thing</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>And lets you write code like this:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">contextlib</span> <span class="k">import</span> <span class="n">closing</span>
|
|||
|
<span class="kn">from</span> <span class="nn">urllib.request</span> <span class="k">import</span> <span class="n">urlopen</span>
|
|||
|
|
|||
|
<span class="k">with</span> <span class="n">closing</span><span class="p">(</span><span class="n">urlopen</span><span class="p">(</span><span class="s1">'http://www.python.org'</span><span class="p">))</span> <span class="k">as</span> <span class="n">page</span><span class="p">:</span>
|
|||
|
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">page</span><span class="p">:</span>
|
|||
|
<span class="nb">print</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>without needing to explicitly close <code class="docutils literal notranslate"><span class="pre">page</span></code>. Even if an error occurs,
|
|||
|
<code class="docutils literal notranslate"><span class="pre">page.close()</span></code> will be called when the <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> block is exited.</p>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<span class="target" id="simplifying-support-for-single-optional-context-managers"></span><dl class="function">
|
|||
|
<dt id="contextlib.nullcontext">
|
|||
|
<code class="descclassname">contextlib.</code><code class="descname">nullcontext</code><span class="sig-paren">(</span><em>enter_result=None</em><span class="sig-paren">)</span><a class="headerlink" href="#contextlib.nullcontext" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>Return a context manager that returns <em>enter_result</em> from <code class="docutils literal notranslate"><span class="pre">__enter__</span></code>, but
|
|||
|
otherwise does nothing. It is intended to be used as a stand-in for an
|
|||
|
optional context manager, for example:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">myfunction</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="n">ignore_exceptions</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
|
|||
|
<span class="k">if</span> <span class="n">ignore_exceptions</span><span class="p">:</span>
|
|||
|
<span class="c1"># Use suppress to ignore all exceptions.</span>
|
|||
|
<span class="n">cm</span> <span class="o">=</span> <span class="n">contextlib</span><span class="o">.</span><span class="n">suppress</span><span class="p">(</span><span class="ne">Exception</span><span class="p">)</span>
|
|||
|
<span class="k">else</span><span class="p">:</span>
|
|||
|
<span class="c1"># Do not ignore any exceptions, cm has no effect.</span>
|
|||
|
<span class="n">cm</span> <span class="o">=</span> <span class="n">contextlib</span><span class="o">.</span><span class="n">nullcontext</span><span class="p">()</span>
|
|||
|
<span class="k">with</span> <span class="n">cm</span><span class="p">:</span>
|
|||
|
<span class="c1"># Do something</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>An example using <em>enter_result</em>:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">process_file</span><span class="p">(</span><span class="n">file_or_path</span><span class="p">):</span>
|
|||
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">file_or_path</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
|
|||
|
<span class="c1"># If string, open file</span>
|
|||
|
<span class="n">cm</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">file_or_path</span><span class="p">)</span>
|
|||
|
<span class="k">else</span><span class="p">:</span>
|
|||
|
<span class="c1"># Caller is responsible for closing file</span>
|
|||
|
<span class="n">cm</span> <span class="o">=</span> <span class="n">nullcontext</span><span class="p">(</span><span class="n">file_or_path</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="k">with</span> <span class="n">cm</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
|
|||
|
<span class="c1"># Perform processing on the file</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<div class="versionadded">
|
|||
|
<p><span class="versionmodified added">New in version 3.7.</span></p>
|
|||
|
</div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<dl class="function">
|
|||
|
<dt id="contextlib.suppress">
|
|||
|
<code class="descclassname">contextlib.</code><code class="descname">suppress</code><span class="sig-paren">(</span><em>*exceptions</em><span class="sig-paren">)</span><a class="headerlink" href="#contextlib.suppress" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>Return a context manager that suppresses any of the specified exceptions
|
|||
|
if they occur in the body of a with statement and then resumes execution
|
|||
|
with the first statement following the end of the with statement.</p>
|
|||
|
<p>As with any other mechanism that completely suppresses exceptions, this
|
|||
|
context manager should be used only to cover very specific errors where
|
|||
|
silently continuing with program execution is known to be the right
|
|||
|
thing to do.</p>
|
|||
|
<p>For example:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">contextlib</span> <span class="k">import</span> <span class="n">suppress</span>
|
|||
|
|
|||
|
<span class="k">with</span> <span class="n">suppress</span><span class="p">(</span><span class="ne">FileNotFoundError</span><span class="p">):</span>
|
|||
|
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s1">'somefile.tmp'</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="k">with</span> <span class="n">suppress</span><span class="p">(</span><span class="ne">FileNotFoundError</span><span class="p">):</span>
|
|||
|
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s1">'someotherfile.tmp'</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>This code is equivalent to:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
|
|||
|
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s1">'somefile.tmp'</span><span class="p">)</span>
|
|||
|
<span class="k">except</span> <span class="ne">FileNotFoundError</span><span class="p">:</span>
|
|||
|
<span class="k">pass</span>
|
|||
|
|
|||
|
<span class="k">try</span><span class="p">:</span>
|
|||
|
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s1">'someotherfile.tmp'</span><span class="p">)</span>
|
|||
|
<span class="k">except</span> <span class="ne">FileNotFoundError</span><span class="p">:</span>
|
|||
|
<span class="k">pass</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>This context manager is <a class="reference internal" href="#reentrant-cms"><span class="std std-ref">reentrant</span></a>.</p>
|
|||
|
<div class="versionadded">
|
|||
|
<p><span class="versionmodified added">New in version 3.4.</span></p>
|
|||
|
</div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<dl class="function">
|
|||
|
<dt id="contextlib.redirect_stdout">
|
|||
|
<code class="descclassname">contextlib.</code><code class="descname">redirect_stdout</code><span class="sig-paren">(</span><em>new_target</em><span class="sig-paren">)</span><a class="headerlink" href="#contextlib.redirect_stdout" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>Context manager for temporarily redirecting <a class="reference internal" href="sys.html#sys.stdout" title="sys.stdout"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.stdout</span></code></a> to
|
|||
|
another file or file-like object.</p>
|
|||
|
<p>This tool adds flexibility to existing functions or classes whose output
|
|||
|
is hardwired to stdout.</p>
|
|||
|
<p>For example, the output of <a class="reference internal" href="functions.html#help" title="help"><code class="xref py py-func docutils literal notranslate"><span class="pre">help()</span></code></a> normally is sent to <em>sys.stdout</em>.
|
|||
|
You can capture that output in a string by redirecting the output to an
|
|||
|
<a class="reference internal" href="io.html#io.StringIO" title="io.StringIO"><code class="xref py py-class docutils literal notranslate"><span class="pre">io.StringIO</span></code></a> object:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">f</span> <span class="o">=</span> <span class="n">io</span><span class="o">.</span><span class="n">StringIO</span><span class="p">()</span>
|
|||
|
<span class="k">with</span> <span class="n">redirect_stdout</span><span class="p">(</span><span class="n">f</span><span class="p">):</span>
|
|||
|
<span class="n">help</span><span class="p">(</span><span class="nb">pow</span><span class="p">)</span>
|
|||
|
<span class="n">s</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">getvalue</span><span class="p">()</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>To send the output of <a class="reference internal" href="functions.html#help" title="help"><code class="xref py py-func docutils literal notranslate"><span class="pre">help()</span></code></a> to a file on disk, redirect the output
|
|||
|
to a regular file:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'help.txt'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
|
|||
|
<span class="k">with</span> <span class="n">redirect_stdout</span><span class="p">(</span><span class="n">f</span><span class="p">):</span>
|
|||
|
<span class="n">help</span><span class="p">(</span><span class="nb">pow</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>To send the output of <a class="reference internal" href="functions.html#help" title="help"><code class="xref py py-func docutils literal notranslate"><span class="pre">help()</span></code></a> to <em>sys.stderr</em>:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">with</span> <span class="n">redirect_stdout</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">):</span>
|
|||
|
<span class="n">help</span><span class="p">(</span><span class="nb">pow</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Note that the global side effect on <a class="reference internal" href="sys.html#sys.stdout" title="sys.stdout"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.stdout</span></code></a> means that this
|
|||
|
context manager is not suitable for use in library code and most threaded
|
|||
|
applications. It also has no effect on the output of subprocesses.
|
|||
|
However, it is still a useful approach for many utility scripts.</p>
|
|||
|
<p>This context manager is <a class="reference internal" href="#reentrant-cms"><span class="std std-ref">reentrant</span></a>.</p>
|
|||
|
<div class="versionadded">
|
|||
|
<p><span class="versionmodified added">New in version 3.4.</span></p>
|
|||
|
</div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<dl class="function">
|
|||
|
<dt id="contextlib.redirect_stderr">
|
|||
|
<code class="descclassname">contextlib.</code><code class="descname">redirect_stderr</code><span class="sig-paren">(</span><em>new_target</em><span class="sig-paren">)</span><a class="headerlink" href="#contextlib.redirect_stderr" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>Similar to <a class="reference internal" href="#contextlib.redirect_stdout" title="contextlib.redirect_stdout"><code class="xref py py-func docutils literal notranslate"><span class="pre">redirect_stdout()</span></code></a> but redirecting
|
|||
|
<a class="reference internal" href="sys.html#sys.stderr" title="sys.stderr"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.stderr</span></code></a> to another file or file-like object.</p>
|
|||
|
<p>This context manager is <a class="reference internal" href="#reentrant-cms"><span class="std std-ref">reentrant</span></a>.</p>
|
|||
|
<div class="versionadded">
|
|||
|
<p><span class="versionmodified added">New in version 3.5.</span></p>
|
|||
|
</div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<dl class="class">
|
|||
|
<dt id="contextlib.ContextDecorator">
|
|||
|
<em class="property">class </em><code class="descclassname">contextlib.</code><code class="descname">ContextDecorator</code><a class="headerlink" href="#contextlib.ContextDecorator" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>A base class that enables a context manager to also be used as a decorator.</p>
|
|||
|
<p>Context managers inheriting from <code class="docutils literal notranslate"><span class="pre">ContextDecorator</span></code> have to implement
|
|||
|
<code class="docutils literal notranslate"><span class="pre">__enter__</span></code> and <code class="docutils literal notranslate"><span class="pre">__exit__</span></code> as normal. <code class="docutils literal notranslate"><span class="pre">__exit__</span></code> retains its optional
|
|||
|
exception handling even when used as a decorator.</p>
|
|||
|
<p><code class="docutils literal notranslate"><span class="pre">ContextDecorator</span></code> is used by <a class="reference internal" href="#contextlib.contextmanager" title="contextlib.contextmanager"><code class="xref py py-func docutils literal notranslate"><span class="pre">contextmanager()</span></code></a>, so you get this
|
|||
|
functionality automatically.</p>
|
|||
|
<p>Example of <code class="docutils literal notranslate"><span class="pre">ContextDecorator</span></code>:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">contextlib</span> <span class="k">import</span> <span class="n">ContextDecorator</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">mycontext</span><span class="p">(</span><span class="n">ContextDecorator</span><span class="p">):</span>
|
|||
|
<span class="k">def</span> <span class="nf">__enter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|||
|
<span class="nb">print</span><span class="p">(</span><span class="s1">'Starting'</span><span class="p">)</span>
|
|||
|
<span class="k">return</span> <span class="bp">self</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">__exit__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">exc</span><span class="p">):</span>
|
|||
|
<span class="nb">print</span><span class="p">(</span><span class="s1">'Finishing'</span><span class="p">)</span>
|
|||
|
<span class="k">return</span> <span class="kc">False</span>
|
|||
|
|
|||
|
<span class="o">>>></span> <span class="nd">@mycontext</span><span class="p">()</span>
|
|||
|
<span class="o">...</span> <span class="k">def</span> <span class="nf">function</span><span class="p">():</span>
|
|||
|
<span class="o">...</span> <span class="nb">print</span><span class="p">(</span><span class="s1">'The bit in the middle'</span><span class="p">)</span>
|
|||
|
<span class="o">...</span>
|
|||
|
<span class="o">>>></span> <span class="n">function</span><span class="p">()</span>
|
|||
|
<span class="n">Starting</span>
|
|||
|
<span class="n">The</span> <span class="n">bit</span> <span class="ow">in</span> <span class="n">the</span> <span class="n">middle</span>
|
|||
|
<span class="n">Finishing</span>
|
|||
|
|
|||
|
<span class="o">>>></span> <span class="k">with</span> <span class="n">mycontext</span><span class="p">():</span>
|
|||
|
<span class="o">...</span> <span class="nb">print</span><span class="p">(</span><span class="s1">'The bit in the middle'</span><span class="p">)</span>
|
|||
|
<span class="o">...</span>
|
|||
|
<span class="n">Starting</span>
|
|||
|
<span class="n">The</span> <span class="n">bit</span> <span class="ow">in</span> <span class="n">the</span> <span class="n">middle</span>
|
|||
|
<span class="n">Finishing</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>This change is just syntactic sugar for any construct of the following form:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">f</span><span class="p">():</span>
|
|||
|
<span class="k">with</span> <span class="n">cm</span><span class="p">():</span>
|
|||
|
<span class="c1"># Do stuff</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p><code class="docutils literal notranslate"><span class="pre">ContextDecorator</span></code> lets you instead write:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nd">@cm</span><span class="p">()</span>
|
|||
|
<span class="k">def</span> <span class="nf">f</span><span class="p">():</span>
|
|||
|
<span class="c1"># Do stuff</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>It makes it clear that the <code class="docutils literal notranslate"><span class="pre">cm</span></code> applies to the whole function, rather than
|
|||
|
just a piece of it (and saving an indentation level is nice, too).</p>
|
|||
|
<p>Existing context managers that already have a base class can be extended by
|
|||
|
using <code class="docutils literal notranslate"><span class="pre">ContextDecorator</span></code> as a mixin class:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">contextlib</span> <span class="k">import</span> <span class="n">ContextDecorator</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">mycontext</span><span class="p">(</span><span class="n">ContextBaseClass</span><span class="p">,</span> <span class="n">ContextDecorator</span><span class="p">):</span>
|
|||
|
<span class="k">def</span> <span class="nf">__enter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|||
|
<span class="k">return</span> <span class="bp">self</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">__exit__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">exc</span><span class="p">):</span>
|
|||
|
<span class="k">return</span> <span class="kc">False</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<div class="admonition note">
|
|||
|
<p class="admonition-title">Note</p>
|
|||
|
<p>As the decorated function must be able to be called multiple times, the
|
|||
|
underlying context manager must support use in multiple <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a>
|
|||
|
statements. If this is not the case, then the original construct with the
|
|||
|
explicit <code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code> statement inside the function should be used.</p>
|
|||
|
</div>
|
|||
|
<div class="versionadded">
|
|||
|
<p><span class="versionmodified added">New in version 3.2.</span></p>
|
|||
|
</div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<dl class="class">
|
|||
|
<dt id="contextlib.ExitStack">
|
|||
|
<em class="property">class </em><code class="descclassname">contextlib.</code><code class="descname">ExitStack</code><a class="headerlink" href="#contextlib.ExitStack" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>A context manager that is designed to make it easy to programmatically
|
|||
|
combine other context managers and cleanup functions, especially those
|
|||
|
that are optional or otherwise driven by input data.</p>
|
|||
|
<p>For example, a set of files may easily be handled in a single with
|
|||
|
statement as follows:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">with</span> <span class="n">ExitStack</span><span class="p">()</span> <span class="k">as</span> <span class="n">stack</span><span class="p">:</span>
|
|||
|
<span class="n">files</span> <span class="o">=</span> <span class="p">[</span><span class="n">stack</span><span class="o">.</span><span class="n">enter_context</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="n">fname</span><span class="p">))</span> <span class="k">for</span> <span class="n">fname</span> <span class="ow">in</span> <span class="n">filenames</span><span class="p">]</span>
|
|||
|
<span class="c1"># All opened files will automatically be closed at the end of</span>
|
|||
|
<span class="c1"># the with statement, even if attempts to open files later</span>
|
|||
|
<span class="c1"># in the list raise an exception</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Each instance maintains a stack of registered callbacks that are called in
|
|||
|
reverse order when the instance is closed (either explicitly or implicitly
|
|||
|
at the end of a <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> statement). Note that callbacks are <em>not</em>
|
|||
|
invoked implicitly when the context stack instance is garbage collected.</p>
|
|||
|
<p>This stack model is used so that context managers that acquire their
|
|||
|
resources in their <code class="docutils literal notranslate"><span class="pre">__init__</span></code> method (such as file objects) can be
|
|||
|
handled correctly.</p>
|
|||
|
<p>Since registered callbacks are invoked in the reverse order of
|
|||
|
registration, this ends up behaving as if multiple nested <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a>
|
|||
|
statements had been used with the registered set of callbacks. This even
|
|||
|
extends to exception handling - if an inner callback suppresses or replaces
|
|||
|
an exception, then outer callbacks will be passed arguments based on that
|
|||
|
updated state.</p>
|
|||
|
<p>This is a relatively low level API that takes care of the details of
|
|||
|
correctly unwinding the stack of exit callbacks. It provides a suitable
|
|||
|
foundation for higher level context managers that manipulate the exit
|
|||
|
stack in application specific ways.</p>
|
|||
|
<div class="versionadded">
|
|||
|
<p><span class="versionmodified added">New in version 3.3.</span></p>
|
|||
|
</div>
|
|||
|
<dl class="method">
|
|||
|
<dt id="contextlib.ExitStack.enter_context">
|
|||
|
<code class="descname">enter_context</code><span class="sig-paren">(</span><em>cm</em><span class="sig-paren">)</span><a class="headerlink" href="#contextlib.ExitStack.enter_context" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>Enters a new context manager and adds its <a class="reference internal" href="../reference/datamodel.html#object.__exit__" title="object.__exit__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__exit__()</span></code></a> method to
|
|||
|
the callback stack. The return value is the result of the context
|
|||
|
manager’s own <a class="reference internal" href="../reference/datamodel.html#object.__enter__" title="object.__enter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__enter__()</span></code></a> method.</p>
|
|||
|
<p>These context managers may suppress exceptions just as they normally
|
|||
|
would if used directly as part of a <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> statement.</p>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<dl class="method">
|
|||
|
<dt id="contextlib.ExitStack.push">
|
|||
|
<code class="descname">push</code><span class="sig-paren">(</span><em>exit</em><span class="sig-paren">)</span><a class="headerlink" href="#contextlib.ExitStack.push" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>Adds a context manager’s <a class="reference internal" href="../reference/datamodel.html#object.__exit__" title="object.__exit__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__exit__()</span></code></a> method to the callback stack.</p>
|
|||
|
<p>As <code class="docutils literal notranslate"><span class="pre">__enter__</span></code> is <em>not</em> invoked, this method can be used to cover
|
|||
|
part of an <a class="reference internal" href="../reference/datamodel.html#object.__enter__" title="object.__enter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__enter__()</span></code></a> implementation with a context manager’s own
|
|||
|
<a class="reference internal" href="../reference/datamodel.html#object.__exit__" title="object.__exit__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__exit__()</span></code></a> method.</p>
|
|||
|
<p>If passed an object that is not a context manager, this method assumes
|
|||
|
it is a callback with the same signature as a context manager’s
|
|||
|
<a class="reference internal" href="../reference/datamodel.html#object.__exit__" title="object.__exit__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__exit__()</span></code></a> method and adds it directly to the callback stack.</p>
|
|||
|
<p>By returning true values, these callbacks can suppress exceptions the
|
|||
|
same way context manager <a class="reference internal" href="../reference/datamodel.html#object.__exit__" title="object.__exit__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__exit__()</span></code></a> methods can.</p>
|
|||
|
<p>The passed in object is returned from the function, allowing this
|
|||
|
method to be used as a function decorator.</p>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<dl class="method">
|
|||
|
<dt id="contextlib.ExitStack.callback">
|
|||
|
<code class="descname">callback</code><span class="sig-paren">(</span><em>callback</em>, <em>*args</em>, <em>**kwds</em><span class="sig-paren">)</span><a class="headerlink" href="#contextlib.ExitStack.callback" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>Accepts an arbitrary callback function and arguments and adds it to
|
|||
|
the callback stack.</p>
|
|||
|
<p>Unlike the other methods, callbacks added this way cannot suppress
|
|||
|
exceptions (as they are never passed the exception details).</p>
|
|||
|
<p>The passed in callback is returned from the function, allowing this
|
|||
|
method to be used as a function decorator.</p>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<dl class="method">
|
|||
|
<dt id="contextlib.ExitStack.pop_all">
|
|||
|
<code class="descname">pop_all</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#contextlib.ExitStack.pop_all" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>Transfers the callback stack to a fresh <a class="reference internal" href="#contextlib.ExitStack" title="contextlib.ExitStack"><code class="xref py py-class docutils literal notranslate"><span class="pre">ExitStack</span></code></a> instance
|
|||
|
and returns it. No callbacks are invoked by this operation - instead,
|
|||
|
they will now be invoked when the new stack is closed (either
|
|||
|
explicitly or implicitly at the end of a <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> statement).</p>
|
|||
|
<p>For example, a group of files can be opened as an “all or nothing”
|
|||
|
operation as follows:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">with</span> <span class="n">ExitStack</span><span class="p">()</span> <span class="k">as</span> <span class="n">stack</span><span class="p">:</span>
|
|||
|
<span class="n">files</span> <span class="o">=</span> <span class="p">[</span><span class="n">stack</span><span class="o">.</span><span class="n">enter_context</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="n">fname</span><span class="p">))</span> <span class="k">for</span> <span class="n">fname</span> <span class="ow">in</span> <span class="n">filenames</span><span class="p">]</span>
|
|||
|
<span class="c1"># Hold onto the close method, but don't call it yet.</span>
|
|||
|
<span class="n">close_files</span> <span class="o">=</span> <span class="n">stack</span><span class="o">.</span><span class="n">pop_all</span><span class="p">()</span><span class="o">.</span><span class="n">close</span>
|
|||
|
<span class="c1"># If opening any file fails, all previously opened files will be</span>
|
|||
|
<span class="c1"># closed automatically. If all files are opened successfully,</span>
|
|||
|
<span class="c1"># they will remain open even after the with statement ends.</span>
|
|||
|
<span class="c1"># close_files() can then be invoked explicitly to close them all.</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<dl class="method">
|
|||
|
<dt id="contextlib.ExitStack.close">
|
|||
|
<code class="descname">close</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#contextlib.ExitStack.close" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>Immediately unwinds the callback stack, invoking callbacks in the
|
|||
|
reverse order of registration. For any context managers and exit
|
|||
|
callbacks registered, the arguments passed in will indicate that no
|
|||
|
exception occurred.</p>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<dl class="class">
|
|||
|
<dt id="contextlib.AsyncExitStack">
|
|||
|
<em class="property">class </em><code class="descclassname">contextlib.</code><code class="descname">AsyncExitStack</code><a class="headerlink" href="#contextlib.AsyncExitStack" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>An <a class="reference internal" href="../reference/datamodel.html#async-context-managers"><span class="std std-ref">asynchronous context manager</span></a>, similar
|
|||
|
to <a class="reference internal" href="#contextlib.ExitStack" title="contextlib.ExitStack"><code class="xref py py-class docutils literal notranslate"><span class="pre">ExitStack</span></code></a>, that supports combining both synchronous and
|
|||
|
asynchronous context managers, as well as having coroutines for
|
|||
|
cleanup logic.</p>
|
|||
|
<p>The <code class="xref py py-meth docutils literal notranslate"><span class="pre">close()</span></code> method is not implemented, <a class="reference internal" href="#contextlib.AsyncExitStack.aclose" title="contextlib.AsyncExitStack.aclose"><code class="xref py py-meth docutils literal notranslate"><span class="pre">aclose()</span></code></a> must be used
|
|||
|
instead.</p>
|
|||
|
<dl class="method">
|
|||
|
<dt id="contextlib.AsyncExitStack.enter_async_context">
|
|||
|
<code class="descname">enter_async_context</code><span class="sig-paren">(</span><em>cm</em><span class="sig-paren">)</span><a class="headerlink" href="#contextlib.AsyncExitStack.enter_async_context" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>Similar to <code class="xref py py-meth docutils literal notranslate"><span class="pre">enter_context()</span></code> but expects an asynchronous context
|
|||
|
manager.</p>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<dl class="method">
|
|||
|
<dt id="contextlib.AsyncExitStack.push_async_exit">
|
|||
|
<code class="descname">push_async_exit</code><span class="sig-paren">(</span><em>exit</em><span class="sig-paren">)</span><a class="headerlink" href="#contextlib.AsyncExitStack.push_async_exit" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>Similar to <code class="xref py py-meth docutils literal notranslate"><span class="pre">push()</span></code> but expects either an asynchronous context manager
|
|||
|
or a coroutine function.</p>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<dl class="method">
|
|||
|
<dt id="contextlib.AsyncExitStack.push_async_callback">
|
|||
|
<code class="descname">push_async_callback</code><span class="sig-paren">(</span><em>callback</em>, <em>*args</em>, <em>**kwds</em><span class="sig-paren">)</span><a class="headerlink" href="#contextlib.AsyncExitStack.push_async_callback" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>Similar to <code class="xref py py-meth docutils literal notranslate"><span class="pre">callback()</span></code> but expects a coroutine function.</p>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<dl class="method">
|
|||
|
<dt id="contextlib.AsyncExitStack.aclose">
|
|||
|
<code class="descname">aclose</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#contextlib.AsyncExitStack.aclose" title="Permalink to this definition">¶</a></dt>
|
|||
|
<dd><p>Similar to <code class="xref py py-meth docutils literal notranslate"><span class="pre">close()</span></code> but properly handles awaitables.</p>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
<p>Continuing the example for <a class="reference internal" href="#contextlib.asynccontextmanager" title="contextlib.asynccontextmanager"><code class="xref py py-func docutils literal notranslate"><span class="pre">asynccontextmanager()</span></code></a>:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">with</span> <span class="n">AsyncExitStack</span><span class="p">()</span> <span class="k">as</span> <span class="n">stack</span><span class="p">:</span>
|
|||
|
<span class="n">connections</span> <span class="o">=</span> <span class="p">[</span><span class="k">await</span> <span class="n">stack</span><span class="o">.</span><span class="n">enter_async_context</span><span class="p">(</span><span class="n">get_connection</span><span class="p">())</span>
|
|||
|
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">)]</span>
|
|||
|
<span class="c1"># All opened connections will automatically be released at the end of</span>
|
|||
|
<span class="c1"># the async with statement, even if attempts to open a connection</span>
|
|||
|
<span class="c1"># later in the list raise an exception.</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<div class="versionadded">
|
|||
|
<p><span class="versionmodified added">New in version 3.7.</span></p>
|
|||
|
</div>
|
|||
|
</dd></dl>
|
|||
|
|
|||
|
</div>
|
|||
|
<div class="section" id="examples-and-recipes">
|
|||
|
<h2>Examples and Recipes<a class="headerlink" href="#examples-and-recipes" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>This section describes some examples and recipes for making effective use of
|
|||
|
the tools provided by <a class="reference internal" href="#module-contextlib" title="contextlib: Utilities for with-statement contexts."><code class="xref py py-mod docutils literal notranslate"><span class="pre">contextlib</span></code></a>.</p>
|
|||
|
<div class="section" id="supporting-a-variable-number-of-context-managers">
|
|||
|
<h3>Supporting a variable number of context managers<a class="headerlink" href="#supporting-a-variable-number-of-context-managers" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>The primary use case for <a class="reference internal" href="#contextlib.ExitStack" title="contextlib.ExitStack"><code class="xref py py-class docutils literal notranslate"><span class="pre">ExitStack</span></code></a> is the one given in the class
|
|||
|
documentation: supporting a variable number of context managers and other
|
|||
|
cleanup operations in a single <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> statement. The variability
|
|||
|
may come from the number of context managers needed being driven by user
|
|||
|
input (such as opening a user specified collection of files), or from
|
|||
|
some of the context managers being optional:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">with</span> <span class="n">ExitStack</span><span class="p">()</span> <span class="k">as</span> <span class="n">stack</span><span class="p">:</span>
|
|||
|
<span class="k">for</span> <span class="n">resource</span> <span class="ow">in</span> <span class="n">resources</span><span class="p">:</span>
|
|||
|
<span class="n">stack</span><span class="o">.</span><span class="n">enter_context</span><span class="p">(</span><span class="n">resource</span><span class="p">)</span>
|
|||
|
<span class="k">if</span> <span class="n">need_special_resource</span><span class="p">():</span>
|
|||
|
<span class="n">special</span> <span class="o">=</span> <span class="n">acquire_special_resource</span><span class="p">()</span>
|
|||
|
<span class="n">stack</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="n">release_special_resource</span><span class="p">,</span> <span class="n">special</span><span class="p">)</span>
|
|||
|
<span class="c1"># Perform operations that use the acquired resources</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>As shown, <a class="reference internal" href="#contextlib.ExitStack" title="contextlib.ExitStack"><code class="xref py py-class docutils literal notranslate"><span class="pre">ExitStack</span></code></a> also makes it quite easy to use <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a>
|
|||
|
statements to manage arbitrary resources that don’t natively support the
|
|||
|
context management protocol.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="catching-exceptions-from-enter-methods">
|
|||
|
<h3>Catching exceptions from <code class="docutils literal notranslate"><span class="pre">__enter__</span></code> methods<a class="headerlink" href="#catching-exceptions-from-enter-methods" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>It is occasionally desirable to catch exceptions from an <code class="docutils literal notranslate"><span class="pre">__enter__</span></code>
|
|||
|
method implementation, <em>without</em> inadvertently catching exceptions from
|
|||
|
the <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> statement body or the context manager’s <code class="docutils literal notranslate"><span class="pre">__exit__</span></code>
|
|||
|
method. By using <a class="reference internal" href="#contextlib.ExitStack" title="contextlib.ExitStack"><code class="xref py py-class docutils literal notranslate"><span class="pre">ExitStack</span></code></a> the steps in the context management
|
|||
|
protocol can be separated slightly in order to allow this:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">stack</span> <span class="o">=</span> <span class="n">ExitStack</span><span class="p">()</span>
|
|||
|
<span class="k">try</span><span class="p">:</span>
|
|||
|
<span class="n">x</span> <span class="o">=</span> <span class="n">stack</span><span class="o">.</span><span class="n">enter_context</span><span class="p">(</span><span class="n">cm</span><span class="p">)</span>
|
|||
|
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
|
|||
|
<span class="c1"># handle __enter__ exception</span>
|
|||
|
<span class="k">else</span><span class="p">:</span>
|
|||
|
<span class="k">with</span> <span class="n">stack</span><span class="p">:</span>
|
|||
|
<span class="c1"># Handle normal case</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Actually needing to do this is likely to indicate that the underlying API
|
|||
|
should be providing a direct resource management interface for use with
|
|||
|
<a class="reference internal" href="../reference/compound_stmts.html#try"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">try</span></code></a>/<a class="reference internal" href="../reference/compound_stmts.html#except"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">except</span></code></a>/<a class="reference internal" href="../reference/compound_stmts.html#finally"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">finally</span></code></a> statements, but not
|
|||
|
all APIs are well designed in that regard. When a context manager is the
|
|||
|
only resource management API provided, then <a class="reference internal" href="#contextlib.ExitStack" title="contextlib.ExitStack"><code class="xref py py-class docutils literal notranslate"><span class="pre">ExitStack</span></code></a> can make it
|
|||
|
easier to handle various situations that can’t be handled directly in a
|
|||
|
<a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> statement.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="cleaning-up-in-an-enter-implementation">
|
|||
|
<h3>Cleaning up in an <code class="docutils literal notranslate"><span class="pre">__enter__</span></code> implementation<a class="headerlink" href="#cleaning-up-in-an-enter-implementation" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>As noted in the documentation of <a class="reference internal" href="#contextlib.ExitStack.push" title="contextlib.ExitStack.push"><code class="xref py py-meth docutils literal notranslate"><span class="pre">ExitStack.push()</span></code></a>, this
|
|||
|
method can be useful in cleaning up an already allocated resource if later
|
|||
|
steps in the <a class="reference internal" href="../reference/datamodel.html#object.__enter__" title="object.__enter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__enter__()</span></code></a> implementation fail.</p>
|
|||
|
<p>Here’s an example of doing this for a context manager that accepts resource
|
|||
|
acquisition and release functions, along with an optional validation function,
|
|||
|
and maps them to the context management protocol:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">contextlib</span> <span class="k">import</span> <span class="n">contextmanager</span><span class="p">,</span> <span class="n">AbstractContextManager</span><span class="p">,</span> <span class="n">ExitStack</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">ResourceManager</span><span class="p">(</span><span class="n">AbstractContextManager</span><span class="p">):</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">acquire_resource</span><span class="p">,</span> <span class="n">release_resource</span><span class="p">,</span> <span class="n">check_resource_ok</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">acquire_resource</span> <span class="o">=</span> <span class="n">acquire_resource</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">release_resource</span> <span class="o">=</span> <span class="n">release_resource</span>
|
|||
|
<span class="k">if</span> <span class="n">check_resource_ok</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|||
|
<span class="k">def</span> <span class="nf">check_resource_ok</span><span class="p">(</span><span class="n">resource</span><span class="p">):</span>
|
|||
|
<span class="k">return</span> <span class="kc">True</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">check_resource_ok</span> <span class="o">=</span> <span class="n">check_resource_ok</span>
|
|||
|
|
|||
|
<span class="nd">@contextmanager</span>
|
|||
|
<span class="k">def</span> <span class="nf">_cleanup_on_error</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|||
|
<span class="k">with</span> <span class="n">ExitStack</span><span class="p">()</span> <span class="k">as</span> <span class="n">stack</span><span class="p">:</span>
|
|||
|
<span class="n">stack</span><span class="o">.</span><span class="n">push</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|||
|
<span class="k">yield</span>
|
|||
|
<span class="c1"># The validation check passed and didn't raise an exception</span>
|
|||
|
<span class="c1"># Accordingly, we want to keep the resource, and pass it</span>
|
|||
|
<span class="c1"># back to our caller</span>
|
|||
|
<span class="n">stack</span><span class="o">.</span><span class="n">pop_all</span><span class="p">()</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">__enter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|||
|
<span class="n">resource</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">acquire_resource</span><span class="p">()</span>
|
|||
|
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_cleanup_on_error</span><span class="p">():</span>
|
|||
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">check_resource_ok</span><span class="p">(</span><span class="n">resource</span><span class="p">):</span>
|
|||
|
<span class="n">msg</span> <span class="o">=</span> <span class="s2">"Failed validation for </span><span class="si">{!r}</span><span class="s2">"</span>
|
|||
|
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="n">msg</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">resource</span><span class="p">))</span>
|
|||
|
<span class="k">return</span> <span class="n">resource</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">__exit__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">exc_details</span><span class="p">):</span>
|
|||
|
<span class="c1"># We don't need to duplicate any of our resource release logic</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">release_resource</span><span class="p">()</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="section" id="replacing-any-use-of-try-finally-and-flag-variables">
|
|||
|
<h3>Replacing any use of <code class="docutils literal notranslate"><span class="pre">try-finally</span></code> and flag variables<a class="headerlink" href="#replacing-any-use-of-try-finally-and-flag-variables" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>A pattern you will sometimes see is a <code class="docutils literal notranslate"><span class="pre">try-finally</span></code> statement with a flag
|
|||
|
variable to indicate whether or not the body of the <code class="docutils literal notranslate"><span class="pre">finally</span></code> clause should
|
|||
|
be executed. In its simplest form (that can’t already be handled just by
|
|||
|
using an <code class="docutils literal notranslate"><span class="pre">except</span></code> clause instead), it looks something like this:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">cleanup_needed</span> <span class="o">=</span> <span class="kc">True</span>
|
|||
|
<span class="k">try</span><span class="p">:</span>
|
|||
|
<span class="n">result</span> <span class="o">=</span> <span class="n">perform_operation</span><span class="p">()</span>
|
|||
|
<span class="k">if</span> <span class="n">result</span><span class="p">:</span>
|
|||
|
<span class="n">cleanup_needed</span> <span class="o">=</span> <span class="kc">False</span>
|
|||
|
<span class="k">finally</span><span class="p">:</span>
|
|||
|
<span class="k">if</span> <span class="n">cleanup_needed</span><span class="p">:</span>
|
|||
|
<span class="n">cleanup_resources</span><span class="p">()</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>As with any <code class="docutils literal notranslate"><span class="pre">try</span></code> statement based code, this can cause problems for
|
|||
|
development and review, because the setup code and the cleanup code can end
|
|||
|
up being separated by arbitrarily long sections of code.</p>
|
|||
|
<p><a class="reference internal" href="#contextlib.ExitStack" title="contextlib.ExitStack"><code class="xref py py-class docutils literal notranslate"><span class="pre">ExitStack</span></code></a> makes it possible to instead register a callback for
|
|||
|
execution at the end of a <code class="docutils literal notranslate"><span class="pre">with</span></code> statement, and then later decide to skip
|
|||
|
executing that callback:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">contextlib</span> <span class="k">import</span> <span class="n">ExitStack</span>
|
|||
|
|
|||
|
<span class="k">with</span> <span class="n">ExitStack</span><span class="p">()</span> <span class="k">as</span> <span class="n">stack</span><span class="p">:</span>
|
|||
|
<span class="n">stack</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="n">cleanup_resources</span><span class="p">)</span>
|
|||
|
<span class="n">result</span> <span class="o">=</span> <span class="n">perform_operation</span><span class="p">()</span>
|
|||
|
<span class="k">if</span> <span class="n">result</span><span class="p">:</span>
|
|||
|
<span class="n">stack</span><span class="o">.</span><span class="n">pop_all</span><span class="p">()</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>This allows the intended cleanup up behaviour to be made explicit up front,
|
|||
|
rather than requiring a separate flag variable.</p>
|
|||
|
<p>If a particular application uses this pattern a lot, it can be simplified
|
|||
|
even further by means of a small helper class:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">contextlib</span> <span class="k">import</span> <span class="n">ExitStack</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">Callback</span><span class="p">(</span><span class="n">ExitStack</span><span class="p">):</span>
|
|||
|
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">callback</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwds</span><span class="p">):</span>
|
|||
|
<span class="nb">super</span><span class="p">(</span><span class="n">Callback</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="fm">__init__</span><span class="p">()</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="n">callback</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwds</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">cancel</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">pop_all</span><span class="p">()</span>
|
|||
|
|
|||
|
<span class="k">with</span> <span class="n">Callback</span><span class="p">(</span><span class="n">cleanup_resources</span><span class="p">)</span> <span class="k">as</span> <span class="n">cb</span><span class="p">:</span>
|
|||
|
<span class="n">result</span> <span class="o">=</span> <span class="n">perform_operation</span><span class="p">()</span>
|
|||
|
<span class="k">if</span> <span class="n">result</span><span class="p">:</span>
|
|||
|
<span class="n">cb</span><span class="o">.</span><span class="n">cancel</span><span class="p">()</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>If the resource cleanup isn’t already neatly bundled into a standalone
|
|||
|
function, then it is still possible to use the decorator form of
|
|||
|
<a class="reference internal" href="#contextlib.ExitStack.callback" title="contextlib.ExitStack.callback"><code class="xref py py-meth docutils literal notranslate"><span class="pre">ExitStack.callback()</span></code></a> to declare the resource cleanup in
|
|||
|
advance:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">contextlib</span> <span class="k">import</span> <span class="n">ExitStack</span>
|
|||
|
|
|||
|
<span class="k">with</span> <span class="n">ExitStack</span><span class="p">()</span> <span class="k">as</span> <span class="n">stack</span><span class="p">:</span>
|
|||
|
<span class="nd">@stack</span><span class="o">.</span><span class="n">callback</span>
|
|||
|
<span class="k">def</span> <span class="nf">cleanup_resources</span><span class="p">():</span>
|
|||
|
<span class="o">...</span>
|
|||
|
<span class="n">result</span> <span class="o">=</span> <span class="n">perform_operation</span><span class="p">()</span>
|
|||
|
<span class="k">if</span> <span class="n">result</span><span class="p">:</span>
|
|||
|
<span class="n">stack</span><span class="o">.</span><span class="n">pop_all</span><span class="p">()</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Due to the way the decorator protocol works, a callback function
|
|||
|
declared this way cannot take any parameters. Instead, any resources to
|
|||
|
be released must be accessed as closure variables.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="using-a-context-manager-as-a-function-decorator">
|
|||
|
<h3>Using a context manager as a function decorator<a class="headerlink" href="#using-a-context-manager-as-a-function-decorator" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p><a class="reference internal" href="#contextlib.ContextDecorator" title="contextlib.ContextDecorator"><code class="xref py py-class docutils literal notranslate"><span class="pre">ContextDecorator</span></code></a> makes it possible to use a context manager in
|
|||
|
both an ordinary <code class="docutils literal notranslate"><span class="pre">with</span></code> statement and also as a function decorator.</p>
|
|||
|
<p>For example, it is sometimes useful to wrap functions or groups of statements
|
|||
|
with a logger that can track the time of entry and time of exit. Rather than
|
|||
|
writing both a function decorator and a context manager for the task,
|
|||
|
inheriting from <a class="reference internal" href="#contextlib.ContextDecorator" title="contextlib.ContextDecorator"><code class="xref py py-class docutils literal notranslate"><span class="pre">ContextDecorator</span></code></a> provides both capabilities in a
|
|||
|
single definition:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">contextlib</span> <span class="k">import</span> <span class="n">ContextDecorator</span>
|
|||
|
<span class="kn">import</span> <span class="nn">logging</span>
|
|||
|
|
|||
|
<span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span><span class="n">level</span><span class="o">=</span><span class="n">logging</span><span class="o">.</span><span class="n">INFO</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">track_entry_and_exit</span><span class="p">(</span><span class="n">ContextDecorator</span><span class="p">):</span>
|
|||
|
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">__enter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|||
|
<span class="n">logging</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">'Entering: </span><span class="si">%s</span><span class="s1">'</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">__exit__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exc_type</span><span class="p">,</span> <span class="n">exc</span><span class="p">,</span> <span class="n">exc_tb</span><span class="p">):</span>
|
|||
|
<span class="n">logging</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">'Exiting: </span><span class="si">%s</span><span class="s1">'</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Instances of this class can be used as both a context manager:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">with</span> <span class="n">track_entry_and_exit</span><span class="p">(</span><span class="s1">'widget loader'</span><span class="p">):</span>
|
|||
|
<span class="nb">print</span><span class="p">(</span><span class="s1">'Some time consuming activity goes here'</span><span class="p">)</span>
|
|||
|
<span class="n">load_widget</span><span class="p">()</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>And also as a function decorator:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nd">@track_entry_and_exit</span><span class="p">(</span><span class="s1">'widget loader'</span><span class="p">)</span>
|
|||
|
<span class="k">def</span> <span class="nf">activity</span><span class="p">():</span>
|
|||
|
<span class="nb">print</span><span class="p">(</span><span class="s1">'Some time consuming activity goes here'</span><span class="p">)</span>
|
|||
|
<span class="n">load_widget</span><span class="p">()</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Note that there is one additional limitation when using context managers
|
|||
|
as function decorators: there’s no way to access the return value of
|
|||
|
<a class="reference internal" href="../reference/datamodel.html#object.__enter__" title="object.__enter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__enter__()</span></code></a>. If that value is needed, then it is still necessary to use
|
|||
|
an explicit <code class="docutils literal notranslate"><span class="pre">with</span></code> statement.</p>
|
|||
|
<div class="admonition seealso">
|
|||
|
<p class="admonition-title">See also</p>
|
|||
|
<dl class="simple">
|
|||
|
<dt><span class="target" id="index-0"></span><a class="pep reference external" href="https://www.python.org/dev/peps/pep-0343"><strong>PEP 343</strong></a> - The “with” statement</dt><dd><p>The specification, background, and examples for the Python <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a>
|
|||
|
statement.</p>
|
|||
|
</dd>
|
|||
|
</dl>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="section" id="single-use-reusable-and-reentrant-context-managers">
|
|||
|
<span id="single-use-reusable-and-reentrant-cms"></span><h2>Single use, reusable and reentrant context managers<a class="headerlink" href="#single-use-reusable-and-reentrant-context-managers" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>Most context managers are written in a way that means they can only be
|
|||
|
used effectively in a <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> statement once. These single use
|
|||
|
context managers must be created afresh each time they’re used -
|
|||
|
attempting to use them a second time will trigger an exception or
|
|||
|
otherwise not work correctly.</p>
|
|||
|
<p>This common limitation means that it is generally advisable to create
|
|||
|
context managers directly in the header of the <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> statement
|
|||
|
where they are used (as shown in all of the usage examples above).</p>
|
|||
|
<p>Files are an example of effectively single use context managers, since
|
|||
|
the first <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> statement will close the file, preventing any
|
|||
|
further IO operations using that file object.</p>
|
|||
|
<p>Context managers created using <a class="reference internal" href="#contextlib.contextmanager" title="contextlib.contextmanager"><code class="xref py py-func docutils literal notranslate"><span class="pre">contextmanager()</span></code></a> are also single use
|
|||
|
context managers, and will complain about the underlying generator failing
|
|||
|
to yield if an attempt is made to use them a second time:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">contextlib</span> <span class="k">import</span> <span class="n">contextmanager</span>
|
|||
|
<span class="gp">>>> </span><span class="nd">@contextmanager</span>
|
|||
|
<span class="gp">... </span><span class="k">def</span> <span class="nf">singleuse</span><span class="p">():</span>
|
|||
|
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s2">"Before"</span><span class="p">)</span>
|
|||
|
<span class="gp">... </span> <span class="k">yield</span>
|
|||
|
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s2">"After"</span><span class="p">)</span>
|
|||
|
<span class="gp">...</span>
|
|||
|
<span class="gp">>>> </span><span class="n">cm</span> <span class="o">=</span> <span class="n">singleuse</span><span class="p">()</span>
|
|||
|
<span class="gp">>>> </span><span class="k">with</span> <span class="n">cm</span><span class="p">:</span>
|
|||
|
<span class="gp">... </span> <span class="k">pass</span>
|
|||
|
<span class="gp">...</span>
|
|||
|
<span class="go">Before</span>
|
|||
|
<span class="go">After</span>
|
|||
|
<span class="gp">>>> </span><span class="k">with</span> <span class="n">cm</span><span class="p">:</span>
|
|||
|
<span class="gp">... </span> <span class="k">pass</span>
|
|||
|
<span class="gp">...</span>
|
|||
|
<span class="gt">Traceback (most recent call last):</span>
|
|||
|
<span class="o">...</span>
|
|||
|
<span class="gr">RuntimeError</span>: <span class="n">generator didn't yield</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<div class="section" id="reentrant-context-managers">
|
|||
|
<span id="reentrant-cms"></span><h3>Reentrant context managers<a class="headerlink" href="#reentrant-context-managers" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>More sophisticated context managers may be “reentrant”. These context
|
|||
|
managers can not only be used in multiple <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> statements,
|
|||
|
but may also be used <em>inside</em> a <code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code> statement that is already
|
|||
|
using the same context manager.</p>
|
|||
|
<p><a class="reference internal" href="threading.html#threading.RLock" title="threading.RLock"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.RLock</span></code></a> is an example of a reentrant context manager, as are
|
|||
|
<a class="reference internal" href="#contextlib.suppress" title="contextlib.suppress"><code class="xref py py-func docutils literal notranslate"><span class="pre">suppress()</span></code></a> and <a class="reference internal" href="#contextlib.redirect_stdout" title="contextlib.redirect_stdout"><code class="xref py py-func docutils literal notranslate"><span class="pre">redirect_stdout()</span></code></a>. Here’s a very simple example of
|
|||
|
reentrant use:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">contextlib</span> <span class="k">import</span> <span class="n">redirect_stdout</span>
|
|||
|
<span class="gp">>>> </span><span class="kn">from</span> <span class="nn">io</span> <span class="k">import</span> <span class="n">StringIO</span>
|
|||
|
<span class="gp">>>> </span><span class="n">stream</span> <span class="o">=</span> <span class="n">StringIO</span><span class="p">()</span>
|
|||
|
<span class="gp">>>> </span><span class="n">write_to_stream</span> <span class="o">=</span> <span class="n">redirect_stdout</span><span class="p">(</span><span class="n">stream</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="k">with</span> <span class="n">write_to_stream</span><span class="p">:</span>
|
|||
|
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s2">"This is written to the stream rather than stdout"</span><span class="p">)</span>
|
|||
|
<span class="gp">... </span> <span class="k">with</span> <span class="n">write_to_stream</span><span class="p">:</span>
|
|||
|
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s2">"This is also written to the stream"</span><span class="p">)</span>
|
|||
|
<span class="gp">...</span>
|
|||
|
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="s2">"This is written directly to stdout"</span><span class="p">)</span>
|
|||
|
<span class="go">This is written directly to stdout</span>
|
|||
|
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">stream</span><span class="o">.</span><span class="n">getvalue</span><span class="p">())</span>
|
|||
|
<span class="go">This is written to the stream rather than stdout</span>
|
|||
|
<span class="go">This is also written to the stream</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Real world examples of reentrancy are more likely to involve multiple
|
|||
|
functions calling each other and hence be far more complicated than this
|
|||
|
example.</p>
|
|||
|
<p>Note also that being reentrant is <em>not</em> the same thing as being thread safe.
|
|||
|
<a class="reference internal" href="#contextlib.redirect_stdout" title="contextlib.redirect_stdout"><code class="xref py py-func docutils literal notranslate"><span class="pre">redirect_stdout()</span></code></a>, for example, is definitely not thread safe, as it
|
|||
|
makes a global modification to the system state by binding <a class="reference internal" href="sys.html#sys.stdout" title="sys.stdout"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.stdout</span></code></a>
|
|||
|
to a different stream.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="reusable-context-managers">
|
|||
|
<span id="reusable-cms"></span><h3>Reusable context managers<a class="headerlink" href="#reusable-context-managers" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>Distinct from both single use and reentrant context managers are “reusable”
|
|||
|
context managers (or, to be completely explicit, “reusable, but not
|
|||
|
reentrant” context managers, since reentrant context managers are also
|
|||
|
reusable). These context managers support being used multiple times, but
|
|||
|
will fail (or otherwise not work correctly) if the specific context manager
|
|||
|
instance has already been used in a containing with statement.</p>
|
|||
|
<p><a class="reference internal" href="threading.html#threading.Lock" title="threading.Lock"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.Lock</span></code></a> is an example of a reusable, but not reentrant,
|
|||
|
context manager (for a reentrant lock, it is necessary to use
|
|||
|
<a class="reference internal" href="threading.html#threading.RLock" title="threading.RLock"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.RLock</span></code></a> instead).</p>
|
|||
|
<p>Another example of a reusable, but not reentrant, context manager is
|
|||
|
<a class="reference internal" href="#contextlib.ExitStack" title="contextlib.ExitStack"><code class="xref py py-class docutils literal notranslate"><span class="pre">ExitStack</span></code></a>, as it invokes <em>all</em> currently registered callbacks
|
|||
|
when leaving any with statement, regardless of where those callbacks
|
|||
|
were added:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">contextlib</span> <span class="k">import</span> <span class="n">ExitStack</span>
|
|||
|
<span class="gp">>>> </span><span class="n">stack</span> <span class="o">=</span> <span class="n">ExitStack</span><span class="p">()</span>
|
|||
|
<span class="gp">>>> </span><span class="k">with</span> <span class="n">stack</span><span class="p">:</span>
|
|||
|
<span class="gp">... </span> <span class="n">stack</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="nb">print</span><span class="p">,</span> <span class="s2">"Callback: from first context"</span><span class="p">)</span>
|
|||
|
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s2">"Leaving first context"</span><span class="p">)</span>
|
|||
|
<span class="gp">...</span>
|
|||
|
<span class="go">Leaving first context</span>
|
|||
|
<span class="go">Callback: from first context</span>
|
|||
|
<span class="gp">>>> </span><span class="k">with</span> <span class="n">stack</span><span class="p">:</span>
|
|||
|
<span class="gp">... </span> <span class="n">stack</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="nb">print</span><span class="p">,</span> <span class="s2">"Callback: from second context"</span><span class="p">)</span>
|
|||
|
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s2">"Leaving second context"</span><span class="p">)</span>
|
|||
|
<span class="gp">...</span>
|
|||
|
<span class="go">Leaving second context</span>
|
|||
|
<span class="go">Callback: from second context</span>
|
|||
|
<span class="gp">>>> </span><span class="k">with</span> <span class="n">stack</span><span class="p">:</span>
|
|||
|
<span class="gp">... </span> <span class="n">stack</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="nb">print</span><span class="p">,</span> <span class="s2">"Callback: from outer context"</span><span class="p">)</span>
|
|||
|
<span class="gp">... </span> <span class="k">with</span> <span class="n">stack</span><span class="p">:</span>
|
|||
|
<span class="gp">... </span> <span class="n">stack</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="nb">print</span><span class="p">,</span> <span class="s2">"Callback: from inner context"</span><span class="p">)</span>
|
|||
|
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s2">"Leaving inner context"</span><span class="p">)</span>
|
|||
|
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s2">"Leaving outer context"</span><span class="p">)</span>
|
|||
|
<span class="gp">...</span>
|
|||
|
<span class="go">Leaving inner context</span>
|
|||
|
<span class="go">Callback: from inner context</span>
|
|||
|
<span class="go">Callback: from outer context</span>
|
|||
|
<span class="go">Leaving outer context</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>As the output from the example shows, reusing a single stack object across
|
|||
|
multiple with statements works correctly, but attempting to nest them
|
|||
|
will cause the stack to be cleared at the end of the innermost with
|
|||
|
statement, which is unlikely to be desirable behaviour.</p>
|
|||
|
<p>Using separate <a class="reference internal" href="#contextlib.ExitStack" title="contextlib.ExitStack"><code class="xref py py-class docutils literal notranslate"><span class="pre">ExitStack</span></code></a> instances instead of reusing a single
|
|||
|
instance avoids that problem:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">contextlib</span> <span class="k">import</span> <span class="n">ExitStack</span>
|
|||
|
<span class="gp">>>> </span><span class="k">with</span> <span class="n">ExitStack</span><span class="p">()</span> <span class="k">as</span> <span class="n">outer_stack</span><span class="p">:</span>
|
|||
|
<span class="gp">... </span> <span class="n">outer_stack</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="nb">print</span><span class="p">,</span> <span class="s2">"Callback: from outer context"</span><span class="p">)</span>
|
|||
|
<span class="gp">... </span> <span class="k">with</span> <span class="n">ExitStack</span><span class="p">()</span> <span class="k">as</span> <span class="n">inner_stack</span><span class="p">:</span>
|
|||
|
<span class="gp">... </span> <span class="n">inner_stack</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="nb">print</span><span class="p">,</span> <span class="s2">"Callback: from inner context"</span><span class="p">)</span>
|
|||
|
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s2">"Leaving inner context"</span><span class="p">)</span>
|
|||
|
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s2">"Leaving outer context"</span><span class="p">)</span>
|
|||
|
<span class="gp">...</span>
|
|||
|
<span class="go">Leaving inner context</span>
|
|||
|
<span class="go">Callback: from inner context</span>
|
|||
|
<span class="go">Leaving outer context</span>
|
|||
|
<span class="go">Callback: from outer context</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
|||
|
<div class="sphinxsidebarwrapper">
|
|||
|
<h3><a href="../contents.html">Table of Contents</a></h3>
|
|||
|
<ul>
|
|||
|
<li><a class="reference internal" href="#"><code class="xref py py-mod docutils literal notranslate"><span class="pre">contextlib</span></code> — Utilities for <code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code>-statement contexts</a><ul>
|
|||
|
<li><a class="reference internal" href="#utilities">Utilities</a></li>
|
|||
|
<li><a class="reference internal" href="#examples-and-recipes">Examples and Recipes</a><ul>
|
|||
|
<li><a class="reference internal" href="#supporting-a-variable-number-of-context-managers">Supporting a variable number of context managers</a></li>
|
|||
|
<li><a class="reference internal" href="#catching-exceptions-from-enter-methods">Catching exceptions from <code class="docutils literal notranslate"><span class="pre">__enter__</span></code> methods</a></li>
|
|||
|
<li><a class="reference internal" href="#cleaning-up-in-an-enter-implementation">Cleaning up in an <code class="docutils literal notranslate"><span class="pre">__enter__</span></code> implementation</a></li>
|
|||
|
<li><a class="reference internal" href="#replacing-any-use-of-try-finally-and-flag-variables">Replacing any use of <code class="docutils literal notranslate"><span class="pre">try-finally</span></code> and flag variables</a></li>
|
|||
|
<li><a class="reference internal" href="#using-a-context-manager-as-a-function-decorator">Using a context manager as a function decorator</a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#single-use-reusable-and-reentrant-context-managers">Single use, reusable and reentrant context managers</a><ul>
|
|||
|
<li><a class="reference internal" href="#reentrant-context-managers">Reentrant context managers</a></li>
|
|||
|
<li><a class="reference internal" href="#reusable-context-managers">Reusable context managers</a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h4>Previous topic</h4>
|
|||
|
<p class="topless"><a href="dataclasses.html"
|
|||
|
title="previous chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">dataclasses</span></code> — Data Classes</a></p>
|
|||
|
<h4>Next topic</h4>
|
|||
|
<p class="topless"><a href="abc.html"
|
|||
|
title="next chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">abc</span></code> — Abstract Base Classes</a></p>
|
|||
|
<div role="note" aria-label="source link">
|
|||
|
<h3>This Page</h3>
|
|||
|
<ul class="this-page-menu">
|
|||
|
<li><a href="../bugs.html">Report a Bug</a></li>
|
|||
|
<li>
|
|||
|
<a href="https://github.com/python/cpython/blob/3.7/Doc/library/contextlib.rst"
|
|||
|
rel="nofollow">Show Source
|
|||
|
</a>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="clearer"></div>
|
|||
|
</div>
|
|||
|
<div class="related" role="navigation" aria-label="related navigation">
|
|||
|
<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="abc.html" title="abc — Abstract Base Classes"
|
|||
|
>next</a> |</li>
|
|||
|
<li class="right" >
|
|||
|
<a href="dataclasses.html" title="dataclasses — Data Classes"
|
|||
|
>previous</a> |</li>
|
|||
|
<li><img src="../_static/py.png" alt=""
|
|||
|
style="vertical-align: middle; margin-top: -1px"/></li>
|
|||
|
<li><a href="https://www.python.org/">Python</a> »</li>
|
|||
|
<li>
|
|||
|
<span class="language_switcher_placeholder">en</span>
|
|||
|
<span class="version_switcher_placeholder">3.7.4</span>
|
|||
|
<a href="../index.html">Documentation </a> »
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> »</li>
|
|||
|
<li class="nav-item nav-item-2"><a href="python.html" >Python Runtime Services</a> »</li>
|
|||
|
<li class="right">
|
|||
|
|
|||
|
|
|||
|
<div class="inline-search" style="display: none" role="search">
|
|||
|
<form class="inline-search" action="../search.html" method="get">
|
|||
|
<input placeholder="Quick search" type="text" name="q" />
|
|||
|
<input type="submit" value="Go" />
|
|||
|
<input type="hidden" name="check_keywords" value="yes" />
|
|||
|
<input type="hidden" name="area" value="default" />
|
|||
|
</form>
|
|||
|
</div>
|
|||
|
<script type="text/javascript">$('.inline-search').show(0);</script>
|
|||
|
|
|
|||
|
</li>
|
|||
|
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
<div class="footer">
|
|||
|
© <a href="../copyright.html">Copyright</a> 2001-2019, Python Software Foundation.
|
|||
|
<br />
|
|||
|
The Python Software Foundation is a non-profit corporation.
|
|||
|
<a href="https://www.python.org/psf/donations/">Please donate.</a>
|
|||
|
<br />
|
|||
|
Last updated on Jul 13, 2019.
|
|||
|
<a href="../bugs.html">Found a bug</a>?
|
|||
|
<br />
|
|||
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 2.0.1.
|
|||
|
</div>
|
|||
|
|
|||
|
</body>
|
|||
|
</html>
|