CINXE.COM
PEP 288 – Generators Attributes and Exceptions | 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 288 – Generators Attributes and Exceptions | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0288/"> <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 288 – Generators Attributes and Exceptions | peps.python.org'> <meta property="og:description" content="This PEP proposes to enhance generators by providing mechanisms for raising exceptions and sharing data with running generators."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0288/"> <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 proposes to enhance generators by providing mechanisms for raising exceptions and sharing data with running generators."> <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 288</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 288 – Generators Attributes and Exceptions</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">Raymond Hettinger <python at rcn.com></dd> <dt class="field-even">Status<span class="colon">:</span></dt> <dd class="field-even"><abbr title="Removed from consideration by sponsor or authors">Withdrawn</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">21-Mar-2002</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="#abstract">Abstract</a></li> <li><a class="reference internal" href="#status">Status</a></li> <li><a class="reference internal" href="#rationale">Rationale</a></li> <li><a class="reference internal" href="#specification-for-generator-attributes">Specification for Generator Attributes</a></li> <li><a class="reference internal" href="#specification-for-generator-exception-passing">Specification for Generator Exception Passing</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="abstract"> <h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2> <p>This PEP proposes to enhance generators by providing mechanisms for raising exceptions and sharing data with running generators.</p> </section> <section id="status"> <h2><a class="toc-backref" href="#status" role="doc-backlink">Status</a></h2> <p>This PEP is withdrawn. The exception raising mechanism was extended and subsumed into <a class="pep reference internal" href="../pep-0343/" title="PEP 343 – The “with” Statement">PEP 343</a>. The attribute passing capability never built a following, did not have a clear implementation, and did not have a clean way for the running generator to access its own namespace.</p> </section> <section id="rationale"> <h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2> <p>Currently, only class based iterators can provide attributes and exception handling. However, class based iterators are harder to write, less compact, less readable, and slower. A better solution is to enable these capabilities for generators.</p> <p>Enabling attribute assignments allows data to be passed to and from running generators. The approach of sharing data using attributes pervades Python. Other approaches exist but are somewhat hackish in comparison.</p> <p>Another evolutionary step is to add a generator method to allow exceptions to be passed to a generator. Currently, there is no clean method for triggering exceptions from outside the generator. Also, generator exception passing helps mitigate the try/finally prohibition for generators. The need is especially acute for generators needing to flush buffers or close resources upon termination.</p> <p>The two proposals are backwards compatible and require no new keywords. They are being recommended for Python version 2.5.</p> </section> <section id="specification-for-generator-attributes"> <h2><a class="toc-backref" href="#specification-for-generator-attributes" role="doc-backlink">Specification for Generator Attributes</a></h2> <p>Essentially, the proposal is to emulate attribute writing for classes. The only wrinkle is that generators lack a way to refer to instances of themselves. So, the proposal is to provide a function for discovering the reference. For example:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">mygen</span><span class="p">(</span><span class="n">filename</span><span class="p">):</span> <span class="bp">self</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">get_generator</span><span class="p">()</span> <span class="n">myfile</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">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">myfile</span><span class="p">:</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">line</span><span class="p">)</span> <span class="o"><</span> <span class="mi">10</span><span class="p">:</span> <span class="k">continue</span> <span class="bp">self</span><span class="o">.</span><span class="n">pos</span> <span class="o">=</span> <span class="n">myfile</span><span class="o">.</span><span class="n">tell</span><span class="p">()</span> <span class="k">yield</span> <span class="n">line</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span> <span class="n">g</span> <span class="o">=</span> <span class="n">mygen</span><span class="p">(</span><span class="s1">'sample.txt'</span><span class="p">)</span> <span class="n">line1</span> <span class="o">=</span> <span class="n">g</span><span class="o">.</span><span class="n">next</span><span class="p">()</span> <span class="nb">print</span> <span class="s1">'Position'</span><span class="p">,</span> <span class="n">g</span><span class="o">.</span><span class="n">pos</span> </pre></div> </div> <p>Uses for generator attributes include:</p> <ol class="arabic simple"> <li>Providing generator clients with extra information (as shown above).</li> <li>Externally setting control flags governing generator operation (possibly telling a generator when to step in or step over data groups).</li> <li>Writing lazy consumers with complex execution states (an arithmetic encoder output stream for example).</li> <li>Writing co-routines (as demonstrated in Dr. Mertz’s articles <a class="footnote-reference brackets" href="#id2" id="id1">[1]</a>).</li> </ol> <p>The control flow of ‘yield’ and ‘next’ is unchanged by this proposal. The only change is that data can passed to and from the generator. Most of the underlying machinery is already in place, only the access function needs to be added.</p> </section> <section id="specification-for-generator-exception-passing"> <h2><a class="toc-backref" href="#specification-for-generator-exception-passing" role="doc-backlink">Specification for Generator Exception Passing</a></h2> <p>Add a <code class="docutils literal notranslate"><span class="pre">.throw(exception)</span></code> method to the generator interface:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">logger</span><span class="p">():</span> <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="n">log</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">try</span><span class="p">:</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="n">log</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">start</span><span class="p">)</span> <span class="k">yield</span> <span class="n">log</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="k">except</span> <span class="n">WriteLog</span><span class="p">:</span> <span class="n">writelog</span><span class="p">(</span><span class="n">log</span><span class="p">)</span> <span class="n">g</span> <span class="o">=</span> <span class="n">logger</span><span class="p">()</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="p">[</span><span class="mi">10</span><span class="p">,</span><span class="mi">20</span><span class="p">,</span><span class="mi">40</span><span class="p">,</span><span class="mi">80</span><span class="p">,</span><span class="mi">160</span><span class="p">]:</span> <span class="n">testsuite</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="n">g</span><span class="o">.</span><span class="n">next</span><span class="p">()</span> <span class="n">g</span><span class="o">.</span><span class="n">throw</span><span class="p">(</span><span class="n">WriteLog</span><span class="p">)</span> </pre></div> </div> <p>There is no existing work-around for triggering an exception inside a generator. It is the only case in Python where active code cannot be excepted to or through.</p> <p>Generator exception passing also helps address an intrinsic limitation on generators, the prohibition against their using try/finally to trigger clean-up code (<a class="pep reference internal" href="../pep-0255/" title="PEP 255 – Simple Generators">PEP 255</a>).</p> <p>Note A: The name of the throw method was selected for several reasons. Raise is a keyword and so cannot be used as a method name. Unlike raise which immediately raises an exception from the current execution point, throw will first return to the generator and then raise the exception. The word throw is suggestive of putting the exception in another location. The word throw is already associated with exceptions in other languages.</p> <p>Alternative method names were considered: <code class="docutils literal notranslate"><span class="pre">resolve()</span></code>, <code class="docutils literal notranslate"><span class="pre">signal()</span></code>, <code class="docutils literal notranslate"><span class="pre">genraise()</span></code>, <code class="docutils literal notranslate"><span class="pre">raiseinto()</span></code>, and <code class="docutils literal notranslate"><span class="pre">flush()</span></code>. None of these fit as well as <code class="docutils literal notranslate"><span class="pre">throw()</span></code>.</p> <p>Note B: To keep the <code class="docutils literal notranslate"><span class="pre">throw()</span></code> syntax simple only the instance version of the raise syntax would be supported (no variants for “<code class="docutils literal notranslate"><span class="pre">raise</span> <span class="pre">string</span></code>” or “<code class="docutils literal notranslate"><span class="pre">raise</span> <span class="pre">class,</span> <span class="pre">instance</span></code>”).</p> <p>Calling <code class="docutils literal notranslate"><span class="pre">g.throw(instance)</span></code> would correspond to writing <code class="docutils literal notranslate"><span class="pre">raise</span> <span class="pre">instance</span></code> immediately after the most recent yield.</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="id2" role="doc-footnote"> <dt class="label" id="id2">[<a href="#id1">1</a>]</dt> <dd>Dr. David Mertz’s draft columns for Charming Python <a class="reference external" href="http://gnosis.cx/publish/programming/charming_python_b5.txt">http://gnosis.cx/publish/programming/charming_python_b5.txt</a> <a class="reference external" href="http://gnosis.cx/publish/programming/charming_python_b7.txt">http://gnosis.cx/publish/programming/charming_python_b7.txt</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-0288.rst">https://github.com/python/peps/blob/main/peps/pep-0288.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0288.rst">2025-02-01 08:55:40 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="#status">Status</a></li> <li><a class="reference internal" href="#rationale">Rationale</a></li> <li><a class="reference internal" href="#specification-for-generator-attributes">Specification for Generator Attributes</a></li> <li><a class="reference internal" href="#specification-for-generator-exception-passing">Specification for Generator Exception Passing</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-0288.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>