mirror of https://github.com/python/peps
648 lines
60 KiB
HTML
648 lines
60 KiB
HTML
|
||
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta name="color-scheme" content="light dark">
|
||
<title>PEP 344 – Exception Chaining and Embedded Tracebacks | peps.python.org</title>
|
||
<link rel="shortcut icon" href="../_static/py.png">
|
||
<link rel="canonical" href="https://peps.python.org/pep-0344/">
|
||
<link rel="stylesheet" href="../_static/style.css" type="text/css">
|
||
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
|
||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
|
||
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
|
||
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
|
||
<meta property="og:title" content='PEP 344 – Exception Chaining and Embedded Tracebacks | peps.python.org'>
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:url" content="https://peps.python.org/pep-0344/">
|
||
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
|
||
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
|
||
<meta property="og:image:alt" content="Python PEPs">
|
||
<meta property="og:image:width" content="200">
|
||
<meta property="og:image:height" content="200">
|
||
<meta name="description" content="Python Enhancement Proposals (PEPs)">
|
||
<meta name="theme-color" content="#3776ab">
|
||
</head>
|
||
<body>
|
||
|
||
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
||
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Following system colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<circle cx="12" cy="12" r="9"></circle>
|
||
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
|
||
</svg>
|
||
</symbol>
|
||
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Selected dark colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
|
||
</svg>
|
||
</symbol>
|
||
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Selected light colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<circle cx="12" cy="12" r="5"></circle>
|
||
<line x1="12" y1="1" x2="12" y2="3"></line>
|
||
<line x1="12" y1="21" x2="12" y2="23"></line>
|
||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
||
<line x1="1" y1="12" x2="3" y2="12"></line>
|
||
<line x1="21" y1="12" x2="23" y2="12"></line>
|
||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
||
</svg>
|
||
</symbol>
|
||
</svg>
|
||
<script>
|
||
|
||
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
|
||
</script>
|
||
<section id="pep-page-section">
|
||
<header>
|
||
<h1>Python Enhancement Proposals</h1>
|
||
<ul class="breadcrumbs">
|
||
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> » </li>
|
||
<li><a href="../pep-0000/">PEP Index</a> » </li>
|
||
<li>PEP 344</li>
|
||
</ul>
|
||
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
|
||
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
|
||
</button>
|
||
</header>
|
||
<article>
|
||
<section id="pep-content">
|
||
<h1 class="page-title">PEP 344 – Exception Chaining and Embedded Tracebacks</h1>
|
||
<dl class="rfc2822 field-list simple">
|
||
<dt class="field-odd">Author<span class="colon">:</span></dt>
|
||
<dd class="field-odd">Ka-Ping Yee</dd>
|
||
<dt class="field-even">Status<span class="colon">:</span></dt>
|
||
<dd class="field-even"><abbr title="Replaced by another succeeding PEP">Superseded</abbr></dd>
|
||
<dt class="field-odd">Type<span class="colon">:</span></dt>
|
||
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
|
||
<dt class="field-even">Created<span class="colon">:</span></dt>
|
||
<dd class="field-even">12-May-2005</dd>
|
||
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
|
||
<dd class="field-odd">2.5</dd>
|
||
<dt class="field-even">Post-History<span class="colon">:</span></dt>
|
||
<dd class="field-even"><p></p></dd>
|
||
</dl>
|
||
<hr class="docutils" />
|
||
<section id="contents">
|
||
<details><summary>Table of Contents</summary><ul class="simple">
|
||
<li><a class="reference internal" href="#numbering-note">Numbering Note</a></li>
|
||
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
||
<li><a class="reference internal" href="#motivation">Motivation</a></li>
|
||
<li><a class="reference internal" href="#history">History</a></li>
|
||
<li><a class="reference internal" href="#rationale">Rationale</a></li>
|
||
<li><a class="reference internal" href="#implicit-exception-chaining">Implicit Exception Chaining</a></li>
|
||
<li><a class="reference internal" href="#explicit-exception-chaining">Explicit Exception Chaining</a></li>
|
||
<li><a class="reference internal" href="#traceback-attribute">Traceback Attribute</a></li>
|
||
<li><a class="reference internal" href="#enhanced-reporting">Enhanced Reporting</a></li>
|
||
<li><a class="reference internal" href="#c-api">C API</a></li>
|
||
<li><a class="reference internal" href="#compatibility">Compatibility</a></li>
|
||
<li><a class="reference internal" href="#open-issue-extra-information">Open Issue: Extra Information</a></li>
|
||
<li><a class="reference internal" href="#open-issue-suppressing-context">Open Issue: Suppressing Context</a></li>
|
||
<li><a class="reference internal" href="#open-issue-limiting-exception-types">Open Issue: Limiting Exception Types</a></li>
|
||
<li><a class="reference internal" href="#open-issue-yield">Open Issue: yield</a></li>
|
||
<li><a class="reference internal" href="#open-issue-garbage-collection">Open Issue: Garbage Collection</a></li>
|
||
<li><a class="reference internal" href="#possible-future-compatible-changes">Possible Future Compatible Changes</a></li>
|
||
<li><a class="reference internal" href="#possible-future-incompatible-changes">Possible Future Incompatible Changes</a></li>
|
||
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</a></li>
|
||
<li><a class="reference internal" href="#references">References</a></li>
|
||
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
||
</ul>
|
||
</details></section>
|
||
<section id="numbering-note">
|
||
<h2><a class="toc-backref" href="#numbering-note" role="doc-backlink">Numbering Note</a></h2>
|
||
<p>This PEP has been renumbered to <a class="pep reference internal" href="../pep-3134/" title="PEP 3134 – Exception Chaining and Embedded Tracebacks">PEP 3134</a>. The text below is the last version
|
||
submitted under the old number.</p>
|
||
</section>
|
||
<section id="abstract">
|
||
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
|
||
<p>This PEP proposes three standard attributes on exception instances: the
|
||
<code class="docutils literal notranslate"><span class="pre">__context__</span></code> attribute for implicitly chained exceptions, the
|
||
<code class="docutils literal notranslate"><span class="pre">__cause__</span></code> attribute for explicitly chained exceptions, and the
|
||
<code class="docutils literal notranslate"><span class="pre">__traceback__</span></code> attribute for the traceback. A new <code class="docutils literal notranslate"><span class="pre">raise</span> <span class="pre">...</span> <span class="pre">from</span></code>
|
||
statement sets the <code class="docutils literal notranslate"><span class="pre">__cause__</span></code> attribute.</p>
|
||
</section>
|
||
<section id="motivation">
|
||
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
|
||
<p>During the handling of one exception (exception A), it is possible that another
|
||
exception (exception B) may occur. In today’s Python (version 2.4), if this
|
||
happens, exception B is propagated outward and exception A is lost. In order
|
||
to debug the problem, it is useful to know about both exceptions. The
|
||
<code class="docutils literal notranslate"><span class="pre">__context__</span></code> attribute retains this information automatically.</p>
|
||
<p>Sometimes it can be useful for an exception handler to intentionally re-raise
|
||
an exception, either to provide extra information or to translate an exception
|
||
to another type. The <code class="docutils literal notranslate"><span class="pre">__cause__</span></code> attribute provides an explicit way to
|
||
record the direct cause of an exception.</p>
|
||
<p>In today’s Python implementation, exceptions are composed of three parts: the
|
||
type, the value, and the traceback. The <code class="docutils literal notranslate"><span class="pre">sys</span></code> module, exposes the current
|
||
exception in three parallel variables, <code class="docutils literal notranslate"><span class="pre">exc_type</span></code>, <code class="docutils literal notranslate"><span class="pre">exc_value</span></code>, and
|
||
<code class="docutils literal notranslate"><span class="pre">exc_traceback</span></code>, the <code class="docutils literal notranslate"><span class="pre">sys.exc_info()</span></code> function returns a tuple of these
|
||
three parts, and the <code class="docutils literal notranslate"><span class="pre">raise</span></code> statement has a three-argument form accepting
|
||
these three parts. Manipulating exceptions often requires passing these three
|
||
things in parallel, which can be tedious and error-prone. Additionally, the
|
||
<code class="docutils literal notranslate"><span class="pre">except</span></code> statement can only provide access to the value, not the traceback.
|
||
Adding the <code class="docutils literal notranslate"><span class="pre">__traceback__</span></code> attribute to exception values makes all the
|
||
exception information accessible from a single place.</p>
|
||
</section>
|
||
<section id="history">
|
||
<h2><a class="toc-backref" href="#history" role="doc-backlink">History</a></h2>
|
||
<p>Raymond Hettinger <a class="footnote-reference brackets" href="#id16" id="id1">[1]</a> raised the issue of masked exceptions on Python-Dev in
|
||
January 2003 and proposed a <code class="docutils literal notranslate"><span class="pre">PyErr_FormatAppend()</span></code> function that C modules
|
||
could use to augment the currently active exception with more information.
|
||
Brett Cannon <a class="footnote-reference brackets" href="#id17" id="id2">[2]</a> brought up chained exceptions again in June 2003, prompting
|
||
a long discussion.</p>
|
||
<p>Greg Ewing <a class="footnote-reference brackets" href="#id18" id="id3">[3]</a> identified the case of an exception occurring in a <code class="docutils literal notranslate"><span class="pre">finally</span></code>
|
||
block during unwinding triggered by an original exception, as distinct from
|
||
the case of an exception occurring in an <code class="docutils literal notranslate"><span class="pre">except</span></code> block that is handling the
|
||
original exception.</p>
|
||
<p>Greg Ewing <a class="footnote-reference brackets" href="#id19" id="id4">[4]</a> and Guido van Rossum <a class="footnote-reference brackets" href="#id20" id="id5">[5]</a>, and probably others, have
|
||
previously mentioned adding a traceback attribute to <code class="docutils literal notranslate"><span class="pre">Exception</span></code> instances.
|
||
This is noted in <a class="pep reference internal" href="../pep-3000/" title="PEP 3000 – Python 3000">PEP 3000</a>.</p>
|
||
<p>This PEP was motivated by yet another recent Python-Dev reposting of the same
|
||
ideas <a class="footnote-reference brackets" href="#id21" id="id6">[6]</a> <a class="footnote-reference brackets" href="#id22" id="id7">[7]</a>.</p>
|
||
</section>
|
||
<section id="rationale">
|
||
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
|
||
<p>The Python-Dev discussions revealed interest in exception chaining for two
|
||
quite different purposes. To handle the unexpected raising of a secondary
|
||
exception, the exception must be retained implicitly. To support intentional
|
||
translation of an exception, there must be a way to chain exceptions
|
||
explicitly. This PEP addresses both.</p>
|
||
<p>Several attribute names for chained exceptions have been suggested on
|
||
Python-Dev <a class="footnote-reference brackets" href="#id17" id="id8">[2]</a>, including <code class="docutils literal notranslate"><span class="pre">cause</span></code>, <code class="docutils literal notranslate"><span class="pre">antecedent</span></code>, <code class="docutils literal notranslate"><span class="pre">reason</span></code>, <code class="docutils literal notranslate"><span class="pre">original</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">chain</span></code>, <code class="docutils literal notranslate"><span class="pre">chainedexc</span></code>, <code class="docutils literal notranslate"><span class="pre">xc_chain</span></code>, <code class="docutils literal notranslate"><span class="pre">excprev</span></code>, <code class="docutils literal notranslate"><span class="pre">previous</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">precursor</span></code>. For an explicitly chained exception, this PEP suggests
|
||
<code class="docutils literal notranslate"><span class="pre">__cause__</span></code> because of its specific meaning. For an implicitly chained
|
||
exception, this PEP proposes the name <code class="docutils literal notranslate"><span class="pre">__context__</span></code> because the intended
|
||
meaning is more specific than temporal precedence but less specific than
|
||
causation: an exception occurs in the context of handling another exception.</p>
|
||
<p>This PEP suggests names with leading and trailing double-underscores for these
|
||
three attributes because they are set by the Python VM. Only in very special
|
||
cases should they be set by normal assignment.</p>
|
||
<p>This PEP handles exceptions that occur during <code class="docutils literal notranslate"><span class="pre">except</span></code> blocks and
|
||
<code class="docutils literal notranslate"><span class="pre">finally</span></code> blocks in the same way. Reading the traceback makes it clear
|
||
where the exceptions occurred, so additional mechanisms for distinguishing
|
||
the two cases would only add unnecessary complexity.</p>
|
||
<p>This PEP proposes that the outermost exception object (the one exposed for
|
||
matching by <code class="docutils literal notranslate"><span class="pre">except</span></code> clauses) be the most recently raised exception for
|
||
compatibility with current behaviour.</p>
|
||
<p>This PEP proposes that tracebacks display the outermost exception last,
|
||
because this would be consistent with the chronological order of tracebacks
|
||
(from oldest to most recent frame) and because the actual thrown exception is
|
||
easier to find on the last line.</p>
|
||
<p>To keep things simpler, the C API calls for setting an exception will not
|
||
automatically set the exception’s <code class="docutils literal notranslate"><span class="pre">__context__</span></code>. Guido van Rossum has
|
||
expressed concerns with making such changes <a class="footnote-reference brackets" href="#id23" id="id9">[8]</a>.</p>
|
||
<p>As for other languages, Java and Ruby both discard the original exception when
|
||
another exception occurs in a <code class="docutils literal notranslate"><span class="pre">catch/rescue</span></code> or <code class="docutils literal notranslate"><span class="pre">finally/ensure</span></code> clause.
|
||
Perl 5 lacks built-in structured exception handling. For Perl 6, RFC number
|
||
88 <a class="footnote-reference brackets" href="#id24" id="id10">[9]</a> proposes an exception mechanism that implicitly retains chained
|
||
exceptions in an array named <code class="docutils literal notranslate"><span class="pre">@@</span></code>. In that RFC, the most recently raised
|
||
exception is exposed for matching, as in this PEP; also, arbitrary expressions
|
||
(possibly involving <code class="docutils literal notranslate"><span class="pre">@@</span></code>) can be evaluated for exception matching.</p>
|
||
<p>Exceptions in C# contain a read-only <code class="docutils literal notranslate"><span class="pre">InnerException</span></code> property that may
|
||
point to another exception. Its documentation <a class="footnote-reference brackets" href="#id25" id="id11">[10]</a> says that “When an
|
||
exception X is thrown as a direct result of a previous exception Y, the
|
||
<code class="docutils literal notranslate"><span class="pre">InnerException</span></code> property of X should contain a reference to Y.” This
|
||
property is not set by the VM automatically; rather, all exception
|
||
constructors take an optional <code class="docutils literal notranslate"><span class="pre">innerException</span></code> argument to set it
|
||
explicitly. The <code class="docutils literal notranslate"><span class="pre">__cause__</span></code> attribute fulfills the same purpose as
|
||
<code class="docutils literal notranslate"><span class="pre">InnerException</span></code>, but this PEP proposes a new form of <code class="docutils literal notranslate"><span class="pre">raise</span></code> rather than
|
||
extending the constructors of all exceptions. C# also provides a
|
||
<code class="docutils literal notranslate"><span class="pre">GetBaseException</span></code> method that jumps directly to the end of the
|
||
<code class="docutils literal notranslate"><span class="pre">InnerException</span></code> chain; this PEP proposes no analog.</p>
|
||
<p>The reason all three of these attributes are presented together in one proposal
|
||
is that the <code class="docutils literal notranslate"><span class="pre">__traceback__</span></code> attribute provides convenient access to the
|
||
traceback on chained exceptions.</p>
|
||
</section>
|
||
<section id="implicit-exception-chaining">
|
||
<h2><a class="toc-backref" href="#implicit-exception-chaining" role="doc-backlink">Implicit Exception Chaining</a></h2>
|
||
<p>Here is an example to illustrate the <code class="docutils literal notranslate"><span class="pre">__context__</span></code> attribute:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">compute</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="n">a</span><span class="o">/</span><span class="n">b</span>
|
||
<span class="k">except</span> <span class="ne">Exception</span><span class="p">,</span> <span class="n">exc</span><span class="p">:</span>
|
||
<span class="n">log</span><span class="p">(</span><span class="n">exc</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">log</span><span class="p">(</span><span class="n">exc</span><span class="p">):</span>
|
||
<span class="n">file</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'logfile.txt'</span><span class="p">)</span> <span class="c1"># oops, forgot the 'w'</span>
|
||
<span class="nb">print</span> <span class="o">>></span><span class="n">file</span><span class="p">,</span> <span class="n">exc</span>
|
||
<span class="n">file</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Calling <code class="docutils literal notranslate"><span class="pre">compute(0,</span> <span class="pre">0)</span></code> causes a <code class="docutils literal notranslate"><span class="pre">ZeroDivisionError</span></code>. The <code class="docutils literal notranslate"><span class="pre">compute()</span></code>
|
||
function catches this exception and calls <code class="docutils literal notranslate"><span class="pre">log(exc)</span></code>, but the <code class="docutils literal notranslate"><span class="pre">log()</span></code>
|
||
function also raises an exception when it tries to write to a file that wasn’t
|
||
opened for writing.</p>
|
||
<p>In today’s Python, the caller of <code class="docutils literal notranslate"><span class="pre">compute()</span></code> gets thrown an <code class="docutils literal notranslate"><span class="pre">IOError</span></code>. The
|
||
<code class="docutils literal notranslate"><span class="pre">ZeroDivisionError</span></code> is lost. With the proposed change, the instance of
|
||
<code class="docutils literal notranslate"><span class="pre">IOError</span></code> has an additional <code class="docutils literal notranslate"><span class="pre">__context__</span></code> attribute that retains the
|
||
<code class="docutils literal notranslate"><span class="pre">ZeroDivisionError</span></code>.</p>
|
||
<p>The following more elaborate example demonstrates the handling of a mixture of
|
||
<code class="docutils literal notranslate"><span class="pre">finally</span></code> and <code class="docutils literal notranslate"><span class="pre">except</span></code> clauses:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="n">filename</span><span class="p">):</span>
|
||
<span class="n">file</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span> <span class="c1"># oops, forgot the 'w'</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="n">compute</span><span class="p">()</span>
|
||
<span class="k">except</span> <span class="ne">Exception</span><span class="p">,</span> <span class="n">exc</span><span class="p">:</span>
|
||
<span class="n">log</span><span class="p">(</span><span class="n">file</span><span class="p">,</span> <span class="n">exc</span><span class="p">)</span>
|
||
<span class="k">finally</span><span class="p">:</span>
|
||
<span class="n">file</span><span class="o">.</span><span class="n">clos</span><span class="p">()</span> <span class="c1"># oops, misspelled 'close'</span>
|
||
|
||
<span class="k">def</span> <span class="nf">compute</span><span class="p">():</span>
|
||
<span class="mi">1</span><span class="o">/</span><span class="mi">0</span>
|
||
|
||
<span class="k">def</span> <span class="nf">log</span><span class="p">(</span><span class="n">file</span><span class="p">,</span> <span class="n">exc</span><span class="p">):</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="nb">print</span> <span class="o">>></span><span class="n">file</span><span class="p">,</span> <span class="n">exc</span> <span class="c1"># oops, file is not writable</span>
|
||
<span class="k">except</span><span class="p">:</span>
|
||
<span class="n">display</span><span class="p">(</span><span class="n">exc</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">display</span><span class="p">(</span><span class="n">exc</span><span class="p">):</span>
|
||
<span class="nb">print</span> <span class="n">ex</span> <span class="c1"># oops, misspelled 'exc'</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Calling <code class="docutils literal notranslate"><span class="pre">main()</span></code> with the name of an existing file will trigger four
|
||
exceptions. The ultimate result will be an <code class="docutils literal notranslate"><span class="pre">AttributeError</span></code> due to the
|
||
misspelling of <code class="docutils literal notranslate"><span class="pre">clos</span></code>, whose <code class="docutils literal notranslate"><span class="pre">__context__</span></code> points to a <code class="docutils literal notranslate"><span class="pre">NameError</span></code> due
|
||
to the misspelling of <code class="docutils literal notranslate"><span class="pre">ex</span></code>, whose <code class="docutils literal notranslate"><span class="pre">__context__</span></code> points to an <code class="docutils literal notranslate"><span class="pre">IOError</span></code>
|
||
due to the file being read-only, whose <code class="docutils literal notranslate"><span class="pre">__context__</span></code> points to a
|
||
<code class="docutils literal notranslate"><span class="pre">ZeroDivisionError</span></code>, whose <code class="docutils literal notranslate"><span class="pre">__context__</span></code> attribute is <code class="docutils literal notranslate"><span class="pre">None</span></code>.</p>
|
||
<p>The proposed semantics are as follows:</p>
|
||
<ol class="arabic simple">
|
||
<li>Each thread has an exception context initially set to <code class="docutils literal notranslate"><span class="pre">None</span></code>.</li>
|
||
<li>Whenever an exception is raised, if the exception instance does not
|
||
already have a <code class="docutils literal notranslate"><span class="pre">__context__</span></code> attribute, the interpreter sets it equal to
|
||
the thread’s exception context.</li>
|
||
<li>Immediately after an exception is raised, the thread’s exception context is
|
||
set to the exception.</li>
|
||
<li>Whenever the interpreter exits an <code class="docutils literal notranslate"><span class="pre">except</span></code> block by reaching the end or
|
||
executing a <code class="docutils literal notranslate"><span class="pre">return</span></code>, <code class="docutils literal notranslate"><span class="pre">yield</span></code>, <code class="docutils literal notranslate"><span class="pre">continue</span></code>, or <code class="docutils literal notranslate"><span class="pre">break</span></code> statement,
|
||
the thread’s exception context is set to <code class="docutils literal notranslate"><span class="pre">None</span></code>.</li>
|
||
</ol>
|
||
</section>
|
||
<section id="explicit-exception-chaining">
|
||
<h2><a class="toc-backref" href="#explicit-exception-chaining" role="doc-backlink">Explicit Exception Chaining</a></h2>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">__cause__</span></code> attribute on exception objects is always initialized to
|
||
<code class="docutils literal notranslate"><span class="pre">None</span></code>. It is set by a new form of the <code class="docutils literal notranslate"><span class="pre">raise</span></code> statement:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">raise</span> <span class="n">EXCEPTION</span> <span class="kn">from</span> <span class="nn">CAUSE</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>which is equivalent to:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">exc</span> <span class="o">=</span> <span class="n">EXCEPTION</span>
|
||
<span class="n">exc</span><span class="o">.</span><span class="n">__cause__</span> <span class="o">=</span> <span class="n">CAUSE</span>
|
||
<span class="k">raise</span> <span class="n">exc</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>In the following example, a database provides implementations for a few
|
||
different kinds of storage, with file storage as one kind. The database
|
||
designer wants errors to propagate as <code class="docutils literal notranslate"><span class="pre">DatabaseError</span></code> objects so that the
|
||
client doesn’t have to be aware of the storage-specific details, but doesn’t
|
||
want to lose the underlying error information:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">DatabaseError</span><span class="p">(</span><span class="n">StandardError</span><span class="p">):</span>
|
||
<span class="k">pass</span>
|
||
|
||
<span class="k">class</span> <span class="nc">FileDatabase</span><span class="p">(</span><span class="n">Database</span><span class="p">):</span>
|
||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span><span class="p">):</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
|
||
<span class="k">except</span> <span class="ne">IOError</span><span class="p">,</span> <span class="n">exc</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="n">DatabaseError</span><span class="p">(</span><span class="s1">'failed to open'</span><span class="p">)</span> <span class="kn">from</span> <span class="nn">exc</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>If the call to <code class="docutils literal notranslate"><span class="pre">open()</span></code> raises an exception, the problem will be reported as
|
||
a <code class="docutils literal notranslate"><span class="pre">DatabaseError</span></code>, with a <code class="docutils literal notranslate"><span class="pre">__cause__</span></code> attribute that reveals the
|
||
<code class="docutils literal notranslate"><span class="pre">IOError</span></code> as the original cause.</p>
|
||
</section>
|
||
<section id="traceback-attribute">
|
||
<h2><a class="toc-backref" href="#traceback-attribute" role="doc-backlink">Traceback Attribute</a></h2>
|
||
<p>The following example illustrates the <code class="docutils literal notranslate"><span class="pre">__traceback__</span></code> attribute:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">do_logged</span><span class="p">(</span><span class="n">file</span><span class="p">,</span> <span class="n">work</span><span class="p">):</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="n">work</span><span class="p">()</span>
|
||
<span class="k">except</span> <span class="ne">Exception</span><span class="p">,</span> <span class="n">exc</span><span class="p">:</span>
|
||
<span class="n">write_exception</span><span class="p">(</span><span class="n">file</span><span class="p">,</span> <span class="n">exc</span><span class="p">)</span>
|
||
<span class="k">raise</span> <span class="n">exc</span>
|
||
|
||
<span class="kn">from</span> <span class="nn">traceback</span> <span class="kn">import</span> <span class="n">format_tb</span>
|
||
|
||
<span class="k">def</span> <span class="nf">write_exception</span><span class="p">(</span><span class="n">file</span><span class="p">,</span> <span class="n">exc</span><span class="p">):</span>
|
||
<span class="o">...</span>
|
||
<span class="nb">type</span> <span class="o">=</span> <span class="n">exc</span><span class="o">.</span><span class="vm">__class__</span>
|
||
<span class="n">message</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">exc</span><span class="p">)</span>
|
||
<span class="n">lines</span> <span class="o">=</span> <span class="n">format_tb</span><span class="p">(</span><span class="n">exc</span><span class="o">.</span><span class="n">__traceback__</span><span class="p">)</span>
|
||
<span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="o">...</span> <span class="nb">type</span> <span class="o">...</span> <span class="n">message</span> <span class="o">...</span> <span class="n">lines</span> <span class="o">...</span><span class="p">)</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>In today’s Python, the <code class="docutils literal notranslate"><span class="pre">do_logged()</span></code> function would have to extract the
|
||
traceback from <code class="docutils literal notranslate"><span class="pre">sys.exc_traceback</span></code> or <code class="docutils literal notranslate"><span class="pre">sys.exc_info()</span></code> <a class="footnote-reference brackets" href="#id17" id="id12">[2]</a> and pass both
|
||
the value and the traceback to <code class="docutils literal notranslate"><span class="pre">write_exception()</span></code>. With the proposed
|
||
change, <code class="docutils literal notranslate"><span class="pre">write_exception()</span></code> simply gets one argument and obtains the
|
||
exception using the <code class="docutils literal notranslate"><span class="pre">__traceback__</span></code> attribute.</p>
|
||
<p>The proposed semantics are as follows:</p>
|
||
<ol class="arabic simple">
|
||
<li>Whenever an exception is caught, if the exception instance does not already
|
||
have a <code class="docutils literal notranslate"><span class="pre">__traceback__</span></code> attribute, the interpreter sets it to the newly
|
||
caught traceback.</li>
|
||
</ol>
|
||
</section>
|
||
<section id="enhanced-reporting">
|
||
<h2><a class="toc-backref" href="#enhanced-reporting" role="doc-backlink">Enhanced Reporting</a></h2>
|
||
<p>The default exception handler will be modified to report chained exceptions.
|
||
The chain of exceptions is traversed by following the <code class="docutils literal notranslate"><span class="pre">__cause__</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">__context__</span></code> attributes, with <code class="docutils literal notranslate"><span class="pre">__cause__</span></code> taking priority. In keeping
|
||
with the chronological order of tracebacks, the most recently raised exception
|
||
is displayed last; that is, the display begins with the description of the
|
||
innermost exception and backs up the chain to the outermost exception. The
|
||
tracebacks are formatted as usual, with one of the lines:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">The</span> <span class="n">above</span> <span class="n">exception</span> <span class="n">was</span> <span class="n">the</span> <span class="n">direct</span> <span class="n">cause</span> <span class="n">of</span> <span class="n">the</span> <span class="n">following</span> <span class="n">exception</span><span class="p">:</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>or</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">During</span> <span class="n">handling</span> <span class="n">of</span> <span class="n">the</span> <span class="n">above</span> <span class="n">exception</span><span class="p">,</span> <span class="n">another</span> <span class="n">exception</span> <span class="n">occurred</span><span class="p">:</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>between tracebacks, depending whether they are linked by <code class="docutils literal notranslate"><span class="pre">__cause__</span></code> or
|
||
<code class="docutils literal notranslate"><span class="pre">__context__</span></code> respectively. Here is a sketch of the procedure:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">print_chain</span><span class="p">(</span><span class="n">exc</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="n">exc</span><span class="o">.</span><span class="n">__cause__</span><span class="p">:</span>
|
||
<span class="n">print_chain</span><span class="p">(</span><span class="n">exc</span><span class="o">.</span><span class="n">__cause__</span><span class="p">)</span>
|
||
<span class="nb">print</span> <span class="s1">'</span><span class="se">\n</span><span class="s1">The above exception was the direct cause...'</span>
|
||
<span class="k">elif</span> <span class="n">exc</span><span class="o">.</span><span class="n">__context__</span><span class="p">:</span>
|
||
<span class="n">print_chain</span><span class="p">(</span><span class="n">exc</span><span class="o">.</span><span class="n">__context__</span><span class="p">)</span>
|
||
<span class="nb">print</span> <span class="s1">'</span><span class="se">\n</span><span class="s1">During handling of the above exception, ...'</span>
|
||
<span class="n">print_exc</span><span class="p">(</span><span class="n">exc</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>In the <code class="docutils literal notranslate"><span class="pre">traceback</span></code> module, the <code class="docutils literal notranslate"><span class="pre">format_exception</span></code>, <code class="docutils literal notranslate"><span class="pre">print_exception</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">print_exc</span></code>, and <code class="docutils literal notranslate"><span class="pre">print_last</span> <span class="pre">functions</span></code> will be updated to accept an
|
||
optional <code class="docutils literal notranslate"><span class="pre">chain</span></code> argument, <code class="docutils literal notranslate"><span class="pre">True</span></code> by default. When this argument is
|
||
<code class="docutils literal notranslate"><span class="pre">True</span></code>, these functions will format or display the entire chain of
|
||
exceptions as just described. When it is <code class="docutils literal notranslate"><span class="pre">False</span></code>, these functions will
|
||
format or display only the outermost exception.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">cgitb</span></code> module should also be updated to display the entire chain of
|
||
exceptions.</p>
|
||
</section>
|
||
<section id="c-api">
|
||
<h2><a class="toc-backref" href="#c-api" role="doc-backlink">C API</a></h2>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">PyErr_Set*</span></code> calls for setting exceptions will not set the
|
||
<code class="docutils literal notranslate"><span class="pre">__context__</span></code> attribute on exceptions. <code class="docutils literal notranslate"><span class="pre">PyErr_NormalizeException</span></code> will
|
||
always set the <code class="docutils literal notranslate"><span class="pre">traceback</span></code> attribute to its <code class="docutils literal notranslate"><span class="pre">tb</span></code> argument and the
|
||
<code class="docutils literal notranslate"><span class="pre">__context__</span></code> and <code class="docutils literal notranslate"><span class="pre">__cause__</span></code> attributes to <code class="docutils literal notranslate"><span class="pre">None</span></code>.</p>
|
||
<p>A new API function, <code class="docutils literal notranslate"><span class="pre">PyErr_SetContext(context)</span></code>, will help C programmers
|
||
provide chained exception information. This function will first normalize the
|
||
current exception so it is an instance, then set its <code class="docutils literal notranslate"><span class="pre">__context__</span></code>
|
||
attribute. A similar API function, <code class="docutils literal notranslate"><span class="pre">PyErr_SetCause(cause)</span></code>, will set the
|
||
<code class="docutils literal notranslate"><span class="pre">__cause__</span></code> attribute.</p>
|
||
</section>
|
||
<section id="compatibility">
|
||
<h2><a class="toc-backref" href="#compatibility" role="doc-backlink">Compatibility</a></h2>
|
||
<p>Chained exceptions expose the type of the most recent exception, so they will
|
||
still match the same <code class="docutils literal notranslate"><span class="pre">except</span></code> clauses as they do now.</p>
|
||
<p>The proposed changes should not break any code unless it sets or uses
|
||
attributes named <code class="docutils literal notranslate"><span class="pre">__context__</span></code>, <code class="docutils literal notranslate"><span class="pre">__cause__</span></code>, or <code class="docutils literal notranslate"><span class="pre">__traceback__</span></code> on
|
||
exception instances. As of 2005-05-12, the Python standard library contains
|
||
no mention of such attributes.</p>
|
||
</section>
|
||
<section id="open-issue-extra-information">
|
||
<h2><a class="toc-backref" href="#open-issue-extra-information" role="doc-backlink">Open Issue: Extra Information</a></h2>
|
||
<p>Walter Dörwald <a class="footnote-reference brackets" href="#id26" id="id13">[11]</a> expressed a desire to attach extra information to an
|
||
exception during its upward propagation without changing its type. This could
|
||
be a useful feature, but it is not addressed by this PEP. It could
|
||
conceivably be addressed by a separate PEP establishing conventions for other
|
||
informational attributes on exceptions.</p>
|
||
</section>
|
||
<section id="open-issue-suppressing-context">
|
||
<h2><a class="toc-backref" href="#open-issue-suppressing-context" role="doc-backlink">Open Issue: Suppressing Context</a></h2>
|
||
<p>As written, this PEP makes it impossible to suppress <code class="docutils literal notranslate"><span class="pre">__context__</span></code>, since
|
||
setting <code class="docutils literal notranslate"><span class="pre">exc.__context__</span></code> to <code class="docutils literal notranslate"><span class="pre">None</span></code> in an <code class="docutils literal notranslate"><span class="pre">except</span></code> or <code class="docutils literal notranslate"><span class="pre">finally</span></code> clause
|
||
will only result in it being set again when <code class="docutils literal notranslate"><span class="pre">exc</span></code> is raised.</p>
|
||
</section>
|
||
<section id="open-issue-limiting-exception-types">
|
||
<h2><a class="toc-backref" href="#open-issue-limiting-exception-types" role="doc-backlink">Open Issue: Limiting Exception Types</a></h2>
|
||
<p>To improve encapsulation, library implementors may want to wrap all
|
||
implementation-level exceptions with an application-level exception. One could
|
||
try to wrap exceptions by writing this:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
|
||
<span class="o">...</span> <span class="n">implementation</span> <span class="n">may</span> <span class="k">raise</span> <span class="n">an</span> <span class="n">exception</span> <span class="o">...</span>
|
||
<span class="k">except</span><span class="p">:</span>
|
||
<span class="kn">import</span> <span class="nn">sys</span>
|
||
<span class="k">raise</span> <span class="n">ApplicationError</span> <span class="kn">from</span> <span class="nn">sys.exc_value</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>or this</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
|
||
<span class="o">...</span> <span class="n">implementation</span> <span class="n">may</span> <span class="k">raise</span> <span class="n">an</span> <span class="n">exception</span> <span class="o">...</span>
|
||
<span class="k">except</span> <span class="ne">Exception</span><span class="p">,</span> <span class="n">exc</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="n">ApplicationError</span> <span class="kn">from</span> <span class="nn">exc</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>but both are somewhat flawed. It would be nice to be able to name the current
|
||
exception in a catch-all <code class="docutils literal notranslate"><span class="pre">except</span></code> clause, but that isn’t addressed here.
|
||
Such a feature would allow something like this:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
|
||
<span class="o">...</span> <span class="n">implementation</span> <span class="n">may</span> <span class="k">raise</span> <span class="n">an</span> <span class="n">exception</span> <span class="o">...</span>
|
||
<span class="k">except</span> <span class="o">*</span><span class="p">,</span> <span class="n">exc</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="n">ApplicationError</span> <span class="kn">from</span> <span class="nn">exc</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="open-issue-yield">
|
||
<h2><a class="toc-backref" href="#open-issue-yield" role="doc-backlink">Open Issue: yield</a></h2>
|
||
<p>The exception context is lost when a <code class="docutils literal notranslate"><span class="pre">yield</span></code> statement is executed; resuming
|
||
the frame after the <code class="docutils literal notranslate"><span class="pre">yield</span></code> does not restore the context. Addressing this
|
||
problem is out of the scope of this PEP; it is not a new problem, as
|
||
demonstrated by the following example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">def</span> <span class="nf">gen</span><span class="p">():</span>
|
||
<span class="gp">... </span> <span class="k">try</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="mi">1</span><span class="o">/</span><span class="mi">0</span>
|
||
<span class="gp">... </span> <span class="k">except</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">yield</span> <span class="mi">3</span>
|
||
<span class="gp">... </span> <span class="k">raise</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">g</span> <span class="o">=</span> <span class="n">gen</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">g</span><span class="o">.</span><span class="n">next</span><span class="p">()</span>
|
||
<span class="go">3</span>
|
||
<span class="gp">>>> </span><span class="n">g</span><span class="o">.</span><span class="n">next</span><span class="p">()</span>
|
||
<span class="go">TypeError: exceptions must be classes, instances, or strings</span>
|
||
<span class="go">(deprecated), not NoneType</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="open-issue-garbage-collection">
|
||
<h2><a class="toc-backref" href="#open-issue-garbage-collection" role="doc-backlink">Open Issue: Garbage Collection</a></h2>
|
||
<p>The strongest objection to this proposal has been that it creates cycles
|
||
between exceptions and stack frames <a class="footnote-reference brackets" href="#id27" id="id14">[12]</a>. Collection of cyclic garbage (and
|
||
therefore resource release) can be greatly delayed:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">try</span><span class="p">:</span>
|
||
<span class="gp">>>> </span> <span class="mi">1</span><span class="o">/</span><span class="mi">0</span>
|
||
<span class="gp">>>> </span><span class="k">except</span> <span class="ne">Exception</span><span class="p">,</span> <span class="n">err</span><span class="p">:</span>
|
||
<span class="gp">>>> </span> <span class="k">pass</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>will introduce a cycle from err -> traceback -> stack frame -> err, keeping
|
||
all locals in the same scope alive until the next GC happens.</p>
|
||
<p>Today, these locals would go out of scope. There is lots of code which
|
||
assumes that “local” resources – particularly open files – will be closed
|
||
quickly. If closure has to wait for the next GC, a program (which runs fine
|
||
today) may run out of file handles.</p>
|
||
<p>Making the <code class="docutils literal notranslate"><span class="pre">__traceback__</span></code> attribute a weak reference would avoid the
|
||
problems with cyclic garbage. Unfortunately, it would make saving the
|
||
<code class="docutils literal notranslate"><span class="pre">Exception</span></code> for later (as <code class="docutils literal notranslate"><span class="pre">unittest</span></code> does) more awkward, and it would not
|
||
allow as much cleanup of the <code class="docutils literal notranslate"><span class="pre">sys</span></code> module.</p>
|
||
<p>A possible alternate solution, suggested by Adam Olsen, would be to instead
|
||
turn the reference from the stack frame to the <code class="docutils literal notranslate"><span class="pre">err</span></code> variable into a weak
|
||
reference when the variable goes out of scope <a class="footnote-reference brackets" href="#id28" id="id15">[13]</a>.</p>
|
||
</section>
|
||
<section id="possible-future-compatible-changes">
|
||
<h2><a class="toc-backref" href="#possible-future-compatible-changes" role="doc-backlink">Possible Future Compatible Changes</a></h2>
|
||
<p>These changes are consistent with the appearance of exceptions as a single
|
||
object rather than a triple at the interpreter level.</p>
|
||
<ul class="simple">
|
||
<li>If <a class="pep reference internal" href="../pep-0340/" title="PEP 340 – Anonymous Block Statements">PEP 340</a> or <a class="pep reference internal" href="../pep-0343/" title="PEP 343 – The “with” Statement">PEP 343</a> is accepted, replace the three (<code class="docutils literal notranslate"><span class="pre">type</span></code>, <code class="docutils literal notranslate"><span class="pre">value</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">traceback</span></code>) arguments to <code class="docutils literal notranslate"><span class="pre">__exit__</span></code> with a single exception argument.</li>
|
||
<li>Deprecate <code class="docutils literal notranslate"><span class="pre">sys.exc_type</span></code>, <code class="docutils literal notranslate"><span class="pre">sys.exc_value</span></code>, <code class="docutils literal notranslate"><span class="pre">sys.exc_traceback</span></code>, and
|
||
<code class="docutils literal notranslate"><span class="pre">sys.exc_info()</span></code> in favour of a single member, <code class="docutils literal notranslate"><span class="pre">sys.exception</span></code>.</li>
|
||
<li>Deprecate <code class="docutils literal notranslate"><span class="pre">sys.last_type</span></code>, <code class="docutils literal notranslate"><span class="pre">sys.last_value</span></code>, and <code class="docutils literal notranslate"><span class="pre">sys.last_traceback</span></code>
|
||
in favour of a single member, <code class="docutils literal notranslate"><span class="pre">sys.last_exception</span></code>.</li>
|
||
<li>Deprecate the three-argument form of the <code class="docutils literal notranslate"><span class="pre">raise</span></code> statement in favour of
|
||
the one-argument form.</li>
|
||
<li>Upgrade <code class="docutils literal notranslate"><span class="pre">cgitb.html()</span></code> to accept a single value as its first argument as
|
||
an alternative to a <code class="docutils literal notranslate"><span class="pre">(type,</span> <span class="pre">value,</span> <span class="pre">traceback)</span></code> tuple.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="possible-future-incompatible-changes">
|
||
<h2><a class="toc-backref" href="#possible-future-incompatible-changes" role="doc-backlink">Possible Future Incompatible Changes</a></h2>
|
||
<p>These changes might be worth considering for Python 3000.</p>
|
||
<ul class="simple">
|
||
<li>Remove <code class="docutils literal notranslate"><span class="pre">sys.exc_type</span></code>, <code class="docutils literal notranslate"><span class="pre">sys.exc_value</span></code>, <code class="docutils literal notranslate"><span class="pre">sys.exc_traceback</span></code>, and
|
||
<code class="docutils literal notranslate"><span class="pre">sys.exc_info()</span></code>.</li>
|
||
<li>Remove <code class="docutils literal notranslate"><span class="pre">sys.last_type</span></code>, <code class="docutils literal notranslate"><span class="pre">sys.last_value</span></code>, and <code class="docutils literal notranslate"><span class="pre">sys.last_traceback</span></code>.</li>
|
||
<li>Replace the three-argument <code class="docutils literal notranslate"><span class="pre">sys.excepthook</span></code> with a one-argument API, and
|
||
changing the <code class="docutils literal notranslate"><span class="pre">cgitb</span></code> module to match.</li>
|
||
<li>Remove the three-argument form of the <code class="docutils literal notranslate"><span class="pre">raise</span></code> statement.</li>
|
||
<li>Upgrade <code class="docutils literal notranslate"><span class="pre">traceback.print_exception</span></code> to accept an <code class="docutils literal notranslate"><span class="pre">exception</span></code> argument
|
||
instead of the <code class="docutils literal notranslate"><span class="pre">type</span></code>, <code class="docutils literal notranslate"><span class="pre">value</span></code>, and <code class="docutils literal notranslate"><span class="pre">traceback</span></code> arguments.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="acknowledgements">
|
||
<h2><a class="toc-backref" href="#acknowledgements" role="doc-backlink">Acknowledgements</a></h2>
|
||
<p>Brett Cannon, Greg Ewing, Guido van Rossum, Jeremy Hylton, Phillip J. Eby,
|
||
Raymond Hettinger, Walter Dörwald, and others.</p>
|
||
</section>
|
||
<section id="references">
|
||
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
|
||
<aside class="footnote-list brackets">
|
||
<aside class="footnote brackets" id="id16" role="doc-footnote">
|
||
<dt class="label" id="id16">[<a href="#id1">1</a>]</dt>
|
||
<dd>Raymond Hettinger, “Idea for avoiding exception masking”
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2003-January/032492.html">https://mail.python.org/pipermail/python-dev/2003-January/032492.html</a></aside>
|
||
<aside class="footnote brackets" id="id17" role="doc-footnote">
|
||
<dt class="label" id="id17">[2]<em> (<a href='#id2'>1</a>, <a href='#id8'>2</a>, <a href='#id12'>3</a>) </em></dt>
|
||
<dd>Brett Cannon explains chained exceptions
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2003-June/036063.html">https://mail.python.org/pipermail/python-dev/2003-June/036063.html</a></aside>
|
||
<aside class="footnote brackets" id="id18" role="doc-footnote">
|
||
<dt class="label" id="id18">[<a href="#id3">3</a>]</dt>
|
||
<dd>Greg Ewing points out masking caused by exceptions during finally
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2003-June/036290.html">https://mail.python.org/pipermail/python-dev/2003-June/036290.html</a></aside>
|
||
<aside class="footnote brackets" id="id19" role="doc-footnote">
|
||
<dt class="label" id="id19">[<a href="#id4">4</a>]</dt>
|
||
<dd>Greg Ewing suggests storing the traceback in the exception object
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2003-June/036092.html">https://mail.python.org/pipermail/python-dev/2003-June/036092.html</a></aside>
|
||
<aside class="footnote brackets" id="id20" role="doc-footnote">
|
||
<dt class="label" id="id20">[<a href="#id5">5</a>]</dt>
|
||
<dd>Guido van Rossum mentions exceptions having a traceback attribute
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2005-April/053060.html">https://mail.python.org/pipermail/python-dev/2005-April/053060.html</a></aside>
|
||
<aside class="footnote brackets" id="id21" role="doc-footnote">
|
||
<dt class="label" id="id21">[<a href="#id6">6</a>]</dt>
|
||
<dd>Ka-Ping Yee, “Tidier Exceptions”
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2005-May/053671.html">https://mail.python.org/pipermail/python-dev/2005-May/053671.html</a></aside>
|
||
<aside class="footnote brackets" id="id22" role="doc-footnote">
|
||
<dt class="label" id="id22">[<a href="#id7">7</a>]</dt>
|
||
<dd>Ka-Ping Yee, “Chained Exceptions”
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2005-May/053672.html">https://mail.python.org/pipermail/python-dev/2005-May/053672.html</a></aside>
|
||
<aside class="footnote brackets" id="id23" role="doc-footnote">
|
||
<dt class="label" id="id23">[<a href="#id9">8</a>]</dt>
|
||
<dd>Guido van Rossum discusses automatic chaining in <code class="docutils literal notranslate"><span class="pre">PyErr_Set*</span></code>
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2003-June/036180.html">https://mail.python.org/pipermail/python-dev/2003-June/036180.html</a></aside>
|
||
<aside class="footnote brackets" id="id24" role="doc-footnote">
|
||
<dt class="label" id="id24">[<a href="#id10">9</a>]</dt>
|
||
<dd>Tony Olensky, “Omnibus Structured Exception/Error Handling Mechanism”
|
||
<a class="reference external" href="http://dev.perl.org/perl6/rfc/88.html">http://dev.perl.org/perl6/rfc/88.html</a></aside>
|
||
<aside class="footnote brackets" id="id25" role="doc-footnote">
|
||
<dt class="label" id="id25">[<a href="#id11">10</a>]</dt>
|
||
<dd>MSDN .NET Framework Library, “Exception.InnerException Property”
|
||
<a class="reference external" href="http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemexceptionclassinnerexceptiontopic.asp">http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemexceptionclassinnerexceptiontopic.asp</a></aside>
|
||
<aside class="footnote brackets" id="id26" role="doc-footnote">
|
||
<dt class="label" id="id26">[<a href="#id13">11</a>]</dt>
|
||
<dd>Walter Dörwald suggests wrapping exceptions to add details
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2003-June/036148.html">https://mail.python.org/pipermail/python-dev/2003-June/036148.html</a></aside>
|
||
<aside class="footnote brackets" id="id27" role="doc-footnote">
|
||
<dt class="label" id="id27">[<a href="#id14">12</a>]</dt>
|
||
<dd>Guido van Rossum restates the objection to cyclic trash
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-3000/2007-January/005322.html">https://mail.python.org/pipermail/python-3000/2007-January/005322.html</a></aside>
|
||
<aside class="footnote brackets" id="id28" role="doc-footnote">
|
||
<dt class="label" id="id28">[<a href="#id15">13</a>]</dt>
|
||
<dd>Adam Olsen suggests using a weakref from stack frame to exception
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-3000/2007-January/005363.html">https://mail.python.org/pipermail/python-3000/2007-January/005363.html</a></aside>
|
||
</aside>
|
||
</section>
|
||
<section id="copyright">
|
||
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
|
||
<p>This document has been placed in the public domain.</p>
|
||
</section>
|
||
</section>
|
||
<hr class="docutils" />
|
||
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0344.rst">https://github.com/python/peps/blob/main/peps/pep-0344.rst</a></p>
|
||
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0344.rst">2023-09-09 17:39:29 GMT</a></p>
|
||
|
||
</article>
|
||
<nav id="pep-sidebar">
|
||
<h2>Contents</h2>
|
||
<ul>
|
||
<li><a class="reference internal" href="#numbering-note">Numbering Note</a></li>
|
||
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
||
<li><a class="reference internal" href="#motivation">Motivation</a></li>
|
||
<li><a class="reference internal" href="#history">History</a></li>
|
||
<li><a class="reference internal" href="#rationale">Rationale</a></li>
|
||
<li><a class="reference internal" href="#implicit-exception-chaining">Implicit Exception Chaining</a></li>
|
||
<li><a class="reference internal" href="#explicit-exception-chaining">Explicit Exception Chaining</a></li>
|
||
<li><a class="reference internal" href="#traceback-attribute">Traceback Attribute</a></li>
|
||
<li><a class="reference internal" href="#enhanced-reporting">Enhanced Reporting</a></li>
|
||
<li><a class="reference internal" href="#c-api">C API</a></li>
|
||
<li><a class="reference internal" href="#compatibility">Compatibility</a></li>
|
||
<li><a class="reference internal" href="#open-issue-extra-information">Open Issue: Extra Information</a></li>
|
||
<li><a class="reference internal" href="#open-issue-suppressing-context">Open Issue: Suppressing Context</a></li>
|
||
<li><a class="reference internal" href="#open-issue-limiting-exception-types">Open Issue: Limiting Exception Types</a></li>
|
||
<li><a class="reference internal" href="#open-issue-yield">Open Issue: yield</a></li>
|
||
<li><a class="reference internal" href="#open-issue-garbage-collection">Open Issue: Garbage Collection</a></li>
|
||
<li><a class="reference internal" href="#possible-future-compatible-changes">Possible Future Compatible Changes</a></li>
|
||
<li><a class="reference internal" href="#possible-future-incompatible-changes">Possible Future Incompatible Changes</a></li>
|
||
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</a></li>
|
||
<li><a class="reference internal" href="#references">References</a></li>
|
||
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
||
</ul>
|
||
|
||
<br>
|
||
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0344.rst">Page Source (GitHub)</a>
|
||
</nav>
|
||
</section>
|
||
<script src="../_static/colour_scheme.js"></script>
|
||
<script src="../_static/wrap_tables.js"></script>
|
||
<script src="../_static/sticky_banner.js"></script>
|
||
</body>
|
||
</html> |