CINXE.COM
PEP 758 – Allow except and except* expressions without parentheses | peps.python.org
<!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 758 – Allow except and except* expressions without parentheses | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0758/"> <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 758 – Allow except and except* expressions without parentheses | peps.python.org'> <meta property="og:description" content="This PEP 1 proposes to allow unparenthesized except and except* blocks in Python’s exception handling syntax only when not using the as clause. Currently, when catching multiple exceptions, parentheses are required around the exception types. This was a..."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0758/"> <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="This PEP 1 proposes to allow unparenthesized except and except* blocks in Python’s exception handling syntax only when not using the as clause. Currently, when catching multiple exceptions, parentheses are required around the exception types. This was a..."> <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 758</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 758 – Allow <code class="docutils literal notranslate"><span class="pre">except</span></code> and <code class="docutils literal notranslate"><span class="pre">except*</span></code> expressions without parentheses</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">Pablo Galindo <pablogsal at python.org>, Brett Cannon <brett at python.org></dd> <dt class="field-even">PEP-Delegate<span class="colon">:</span></dt> <dd class="field-even">TBD</dd> <dt class="field-odd">Status<span class="colon">:</span></dt> <dd class="field-odd"><abbr title="Proposal under active discussion and revision">Draft</abbr></dd> <dt class="field-even">Type<span class="colon">:</span></dt> <dd class="field-even"><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-odd">Created<span class="colon">:</span></dt> <dd class="field-odd">30-Sep-2024</dd> <dt class="field-even">Python-Version<span class="colon">:</span></dt> <dd class="field-even">3.14</dd> <dt class="field-odd">Post-History<span class="colon">:</span></dt> <dd class="field-odd"><a class="reference external" href="https://discuss.python.org/t/66453" title="Discourse thread">02-Oct-2024</a></dd> </dl> <hr class="docutils" /> <section id="contents"> <details><summary>Table of Contents</summary><ul class="simple"> <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="#rationale">Rationale</a></li> <li><a class="reference internal" href="#specification">Specification</a></li> <li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li> <li><a class="reference internal" href="#security-implications">Security Implications</a></li> <li><a class="reference internal" href="#how-to-teach-this">How to Teach This</a></li> <li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li> <li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a></li> <li><a class="reference internal" href="#deferred-ideas">Deferred Ideas</a></li> <li><a class="reference internal" href="#footnotes">Footnotes</a></li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> </details></section> <section id="abstract"> <h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2> <p>This PEP <a class="footnote-reference brackets" href="#id2" id="id1">[1]</a> proposes to allow unparenthesized <code class="docutils literal notranslate"><span class="pre">except</span></code> and <code class="docutils literal notranslate"><span class="pre">except*</span></code> blocks in Python’s exception handling syntax only when not using the <code class="docutils literal notranslate"><span class="pre">as</span></code> clause. Currently, when catching multiple exceptions, parentheses are required around the exception types. This was a Python 2 remnant. This PEP suggests allowing the omission of these parentheses, simplifying the syntax, making it more consistent with other parts of the syntax that make parentheses optional, and improving readability in certain cases.</p> </section> <section id="motivation"> <h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2> <p>The current syntax for catching multiple exceptions requires parentheses in the <code class="docutils literal notranslate"><span class="pre">except</span></code> expression (equivalently for the <code class="docutils literal notranslate"><span class="pre">except*</span></code> expression). For example:</p> <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span> <span class="o">...</span> <span class="k">except</span> <span class="p">(</span><span class="n">ExceptionA</span><span class="p">,</span> <span class="n">ExceptionB</span><span class="p">,</span> <span class="n">ExceptionC</span><span class="p">):</span> <span class="o">...</span> </pre></div> </div> <p>While this syntax is clear and unambiguous, it can be seen as unnecessarily verbose in some cases, especially when catching a large number of exceptions. By allowing the omission of parentheses, we can simplify the syntax:</p> <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span> <span class="o">...</span> <span class="k">except</span> <span class="n">ExceptionA</span><span class="p">,</span> <span class="n">ExceptionB</span><span class="p">,</span> <span class="n">ExceptionC</span><span class="p">:</span> <span class="o">...</span> </pre></div> </div> <p>This change would bring the syntax more in line with other comma-separated lists in Python, such as function arguments, generator expressions inside of a function call, and tuple literals, where parentheses are optional.</p> <p>The same change would apply to <code class="docutils literal notranslate"><span class="pre">except*</span></code> expressions. For example:</p> <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span> <span class="o">...</span> <span class="k">except</span><span class="o">*</span> <span class="n">ExceptionA</span><span class="p">,</span> <span class="n">ExceptionB</span><span class="p">,</span> <span class="n">ExceptionC</span><span class="p">:</span> <span class="o">...</span> </pre></div> </div> <p>When using the <code class="docutils literal notranslate"><span class="pre">as</span></code> clause to capture the exception instance paretheses must be used as before. Some users have expressed that they would find it confusing not to require parentheses as it would be unclear what exactly is being assigned to the target since in other parts of the language multiple <code class="docutils literal notranslate"><span class="pre">as</span></code> clauses can be used in similar situations (like in imports and context managers). This means that if an <code class="docutils literal notranslate"><span class="pre">as</span></code> clause its being added to the previous example it must be done as:</p> <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span> <span class="o">...</span> <span class="k">except</span> <span class="p">(</span><span class="n">ExceptionA</span><span class="p">,</span> <span class="n">ExceptionB</span><span class="p">,</span> <span class="n">ExceptionC</span><span class="p">)</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> <span class="o">...</span> </pre></div> </div> </section> <section id="rationale"> <h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2> <p>The decision to allow unparenthesized <code class="docutils literal notranslate"><span class="pre">except</span></code> blocks is based on the following considerations:</p> <ol class="arabic simple"> <li>Simplicity: Removing the requirement for parentheses simplifies the syntax, making it more consistent with other parts of the language.</li> <li>Readability: In cases where many exceptions are being caught, the removal of parentheses can improve readability by reducing visual clutter.</li> <li>Consistency: This change makes the <code class="docutils literal notranslate"><span class="pre">except</span></code> clause more consistent with other parts of Python where unambiguous, comma-separated lists don’t require parentheses.</li> </ol> </section> <section id="specification"> <h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2> <p>The syntax for the except clause will be modified to allow an unparenthesized list of exception types. The grammar will be updated as follows:</p> <div class="highlight-peg notranslate"><div class="highlight"><pre><span></span><span class="nc">except_block</span><span class="o">:</span> <span class="o">|</span> <span class="s1">'except'</span> <span class="nc">expressions</span> <span class="s1">':'</span> <span class="nc">block</span> <span class="o">|</span> <span class="s1">'except'</span> <span class="nc">expression</span> <span class="s1">'as'</span> <span class="nc">NAME</span> <span class="s1">':'</span> <span class="nc">block</span> <span class="o">|</span> <span class="s1">'except'</span> <span class="s1">':'</span> <span class="nc">block</span> <span class="nc">except_star_block</span> <span class="o">|</span> <span class="s1">'except'</span> <span class="s1">'*'</span> <span class="nc">expressions</span> <span class="s1">':'</span> <span class="nc">block</span> <span class="o">|</span> <span class="s1">'except'</span> <span class="s1">'*'</span> <span class="nc">expression</span> <span class="s1">'as'</span> <span class="nc">NAME</span> <span class="s1">':'</span> <span class="nc">block</span> </pre></div> </div> <p>This allows both the current parenthesized syntax and the new unparenthesized syntax while requiring parentheses when the <code class="docutils literal notranslate"><span class="pre">as</span></code> keyword is used:</p> <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span> <span class="o">...</span> <span class="k">except</span> <span class="p">(</span><span class="n">ExceptionA</span><span class="p">,</span> <span class="n">ExceptionB</span><span class="p">):</span> <span class="c1"># Still valid</span> <span class="o">...</span> <span class="k">except</span> <span class="n">ExceptionC</span><span class="p">,</span> <span class="n">ExceptionD</span><span class="p">:</span> <span class="c1"># New syntax</span> <span class="o">...</span> <span class="k">except</span> <span class="p">(</span><span class="n">ExceptionE</span><span class="p">,</span> <span class="n">ExceptionF</span><span class="p">)</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> <span class="c1"># Parentheses still required</span> <span class="o">...</span> </pre></div> </div> <p>The semantics of exception handling remain unchanged. The interpreter will catch any of the listed exceptions, regardless of whether they are parenthesized or not.</p> </section> <section id="backwards-compatibility"> <h2><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards Compatibility</a></h2> <p>This change is fully backwards compatible. All existing code using parenthesized <code class="docutils literal notranslate"><span class="pre">except</span></code> and <code class="docutils literal notranslate"><span class="pre">except*</span></code> blocks will continue to work without modification. The new syntax is purely additive and does not break any existing code.</p> <p>It’s worth noting that in Python 2 the unparenthesized syntax was allowed with two elements, but had different semantics, in which the first element of the list was used as the exception type and the second element as the capture variable. This change does not reintroduce the Python 2 semantics, and the unparenthesized syntax will behave identically to the parenthesized version.</p> </section> <section id="security-implications"> <h2><a class="toc-backref" href="#security-implications" role="doc-backlink">Security Implications</a></h2> <p>There are no known security implications for this change. The semantics of exception handling remain the same, and this is purely a syntactic change.</p> </section> <section id="how-to-teach-this"> <h2><a class="toc-backref" href="#how-to-teach-this" role="doc-backlink">How to Teach This</a></h2> <p>For new Python users, the unparenthesized syntax can be taught as the standard way to catch multiple exceptions:</p> <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span> <span class="n">risky_operation</span><span class="p">()</span> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">,</span> <span class="ne">TypeError</span><span class="p">,</span> <span class="ne">OSError</span><span class="p">:</span> <span class="n">handle_errors</span><span class="p">()</span> </pre></div> </div> <p>For experienced users, it can be introduced as a new, optional syntax that can be used interchangeably with the parenthesized version. Documentation should note that both forms are equivalent:</p> <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># These are equivalent:</span> <span class="k">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">TypeError</span><span class="p">):</span> <span class="o">...</span> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">,</span> <span class="ne">TypeError</span><span class="p">:</span> <span class="o">...</span> </pre></div> </div> <p>It should be emphasized that this is purely a syntactic change and does not affect the behaviour of exception handling.</p> </section> <section id="reference-implementation"> <h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2> <p>A proof-of-concept implementation is available at <a class="reference external" href="https://github.com/pablogsal/cpython/commits/notuples/">https://github.com/pablogsal/cpython/commits/notuples/</a>. This implementation modifies the Python parser to accept the new syntax and ensures that it behaves identically to the parenthesized version.</p> </section> <section id="rejected-ideas"> <h2><a class="toc-backref" href="#rejected-ideas" role="doc-backlink">Rejected Ideas</a></h2> <ol class="arabic"> <li>Allowing mixed parenthesized and unparenthesized syntax:<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span> <span class="o">...</span> <span class="k">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">TypeError</span><span class="p">),</span> <span class="ne">OSError</span><span class="p">:</span> <span class="o">...</span> </pre></div> </div> <p>This was rejected due to the potential for confusion and to maintain a clear distinction between the two styles.</p> </li> </ol> </section> <section id="deferred-ideas"> <h2><a class="toc-backref" href="#deferred-ideas" role="doc-backlink">Deferred Ideas</a></h2> <ol class="arabic simple"> <li>Allowing unparenthesized expressions when the <code class="docutils literal notranslate"><span class="pre">as</span></code> keyword is used. The reason we have decided to defer this particular form given that there isn’t clear consensus either way and there are reasonable arguments for both positions, the safest approach is keeping the parentheses requirement since it can be removed later if users find the disconnect too acute, while taking it out and users deciding it was a bad idea doesn’t make it easy to put back.</li> </ol> </section> <section id="footnotes"> <h2><a class="toc-backref" href="#footnotes" role="doc-backlink">Footnotes</a></h2> <aside class="footnote-list brackets"> <aside class="footnote brackets" id="id2" role="doc-footnote"> <dt class="label" id="id2">[<a href="#id1">1</a>]</dt> <dd>Originally named “Parenthetically Speaking, We Don’t Need ‘Em”</aside> </aside> </section> <section id="copyright"> <h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2> <p>This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.</p> </section> </section> <hr class="docutils" /> <p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0758.rst">https://github.com/python/peps/blob/main/peps/pep-0758.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0758.rst">2024-10-19 19:41:51 GMT</a></p> </article> <nav id="pep-sidebar"> <h2>Contents</h2> <ul> <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="#rationale">Rationale</a></li> <li><a class="reference internal" href="#specification">Specification</a></li> <li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li> <li><a class="reference internal" href="#security-implications">Security Implications</a></li> <li><a class="reference internal" href="#how-to-teach-this">How to Teach This</a></li> <li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li> <li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a></li> <li><a class="reference internal" href="#deferred-ideas">Deferred Ideas</a></li> <li><a class="reference internal" href="#footnotes">Footnotes</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-0758.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>