peps/pep-0492/index.html

1587 lines
143 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!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 492 Coroutines with async and await syntax | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0492/">
<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 492 Coroutines with async and await syntax | peps.python.org'>
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0492/">
<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> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 492</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 492 Coroutines with async and await syntax</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Yury Selivanov &lt;yury&#32;&#97;t&#32;edgedb.com&gt;</dd>
<dt class="field-even">Discussions-To<span class="colon">:</span></dt>
<dd class="field-even"><a class="reference external" href="https://mail.python.org/archives/list/python-dev&#64;python.org/">Python-Dev list</a></dd>
<dt class="field-odd">Status<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Accepted and implementation complete, or no longer active">Final</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">09-Apr-2015</dd>
<dt class="field-even">Python-Version<span class="colon">:</span></dt>
<dd class="field-even">3.5</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd">17-Apr-2015, 21-Apr-2015, 27-Apr-2015, 29-Apr-2015, 05-May-2015</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="#api-design-and-implementation-revisions">API Design and Implementation Revisions</a></li>
<li><a class="reference internal" href="#rationale-and-goals">Rationale and Goals</a></li>
<li><a class="reference internal" href="#specification">Specification</a><ul>
<li><a class="reference internal" href="#new-coroutine-declaration-syntax">New Coroutine Declaration Syntax</a></li>
<li><a class="reference internal" href="#types-coroutine">types.coroutine()</a></li>
<li><a class="reference internal" href="#await-expression">Await Expression</a><ul>
<li><a class="reference internal" href="#updated-operator-precedence-table">Updated operator precedence table</a></li>
<li><a class="reference internal" href="#examples-of-await-expressions">Examples of “await” expressions</a></li>
</ul>
</li>
<li><a class="reference internal" href="#asynchronous-context-managers-and-async-with">Asynchronous Context Managers and “async with”</a><ul>
<li><a class="reference internal" href="#new-syntax">New Syntax</a></li>
<li><a class="reference internal" href="#example">Example</a></li>
</ul>
</li>
<li><a class="reference internal" href="#asynchronous-iterators-and-async-for">Asynchronous Iterators and “async for”</a><ul>
<li><a class="reference internal" href="#id12">New Syntax</a></li>
<li><a class="reference internal" href="#example-1">Example 1</a></li>
<li><a class="reference internal" href="#example-2">Example 2</a></li>
<li><a class="reference internal" href="#why-stopasynciteration">Why StopAsyncIteration?</a></li>
</ul>
</li>
<li><a class="reference internal" href="#coroutine-objects">Coroutine objects</a><ul>
<li><a class="reference internal" href="#differences-from-generators">Differences from generators</a></li>
<li><a class="reference internal" href="#coroutine-object-methods">Coroutine object methods</a></li>
</ul>
</li>
<li><a class="reference internal" href="#debugging-features">Debugging Features</a></li>
<li><a class="reference internal" href="#new-standard-library-functions">New Standard Library Functions</a></li>
<li><a class="reference internal" href="#new-abstract-base-classes">New Abstract Base Classes</a></li>
</ul>
</li>
<li><a class="reference internal" href="#glossary">Glossary</a></li>
<li><a class="reference internal" href="#transition-plan">Transition Plan</a><ul>
<li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a><ul>
<li><a class="reference internal" href="#asyncio">asyncio</a></li>
<li><a class="reference internal" href="#asyncio-migration-strategy">asyncio migration strategy</a></li>
<li><a class="reference internal" href="#async-await-in-cpython-code-base">async/await in CPython code base</a></li>
</ul>
</li>
<li><a class="reference internal" href="#grammar-updates">Grammar Updates</a></li>
<li><a class="reference internal" href="#deprecation-plans">Deprecation Plans</a></li>
</ul>
</li>
<li><a class="reference internal" href="#design-considerations">Design Considerations</a><ul>
<li><a class="reference internal" href="#pep-3152">PEP 3152</a></li>
<li><a class="reference internal" href="#coroutine-generators">Coroutine-generators</a></li>
<li><a class="reference internal" href="#why-async-and-await-keywords">Why “async” and “await” keywords</a></li>
<li><a class="reference internal" href="#why-aiter-does-not-return-an-awaitable">Why “__aiter__” does not return an awaitable</a></li>
<li><a class="reference internal" href="#importance-of-async-keyword">Importance of “async” keyword</a></li>
<li><a class="reference internal" href="#why-async-def">Why “async def”</a></li>
<li><a class="reference internal" href="#why-not-await-for-and-await-with">Why not “await for” and “await with”</a></li>
<li><a class="reference internal" href="#why-async-def-and-not-def-async">Why “async def” and not “def async”</a></li>
<li><a class="reference internal" href="#why-not-a-future-import">Why not a __future__ import</a></li>
<li><a class="reference internal" href="#why-magic-methods-start-with-a">Why magic methods start with “a”</a></li>
<li><a class="reference internal" href="#why-not-reuse-existing-magic-names">Why not reuse existing magic names</a></li>
<li><a class="reference internal" href="#why-not-reuse-existing-for-and-with-statements">Why not reuse existing “for” and “with” statements</a></li>
<li><a class="reference internal" href="#comprehensions">Comprehensions</a></li>
<li><a class="reference internal" href="#async-lambda-functions">Async lambda functions</a></li>
</ul>
</li>
<li><a class="reference internal" href="#performance">Performance</a><ul>
<li><a class="reference internal" href="#overall-impact">Overall Impact</a></li>
<li><a class="reference internal" href="#tokenizer-modifications">Tokenizer modifications</a></li>
<li><a class="reference internal" href="#async-await">async/await</a></li>
</ul>
</li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a><ul>
<li><a class="reference internal" href="#list-of-high-level-changes-and-new-protocols">List of high-level changes and new protocols</a></li>
<li><a class="reference internal" href="#working-example">Working example</a></li>
</ul>
</li>
<li><a class="reference internal" href="#acceptance">Acceptance</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#acknowledgments">Acknowledgments</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>The growth of Internet and general connectivity has triggered the
proportionate need for responsive and scalable code. This proposal
aims to answer that need by making writing explicitly asynchronous,
concurrent Python code easier and more Pythonic.</p>
<p>It is proposed to make <em>coroutines</em> a proper standalone concept in
Python, and introduce new supporting syntax. The ultimate goal
is to help establish a common, easily approachable, mental
model of asynchronous programming in Python and make it as close to
synchronous programming as possible.</p>
<p>This PEP assumes that the asynchronous tasks are scheduled and
coordinated by an Event Loop similar to that of stdlib module
<code class="docutils literal notranslate"><span class="pre">asyncio.events.AbstractEventLoop</span></code>. While the PEP is not tied to any
specific Event Loop implementation, it is relevant only to the kind of
coroutine that uses <code class="docutils literal notranslate"><span class="pre">yield</span></code> as a signal to the scheduler, indicating
that the coroutine will be waiting until an event (such as IO) is
completed.</p>
<p>We believe that the changes proposed here will help keep Python
relevant and competitive in a quickly growing area of asynchronous
programming, as many other languages have adopted, or are planning to
adopt, similar features: <a class="footnote-reference brackets" href="#id32" id="id1">[2]</a>, <a class="footnote-reference brackets" href="#id35" id="id2">[5]</a>, <a class="footnote-reference brackets" href="#id36" id="id3">[6]</a>, <a class="footnote-reference brackets" href="#id37" id="id4">[7]</a>, <a class="footnote-reference brackets" href="#id38" id="id5">[8]</a>, <a class="footnote-reference brackets" href="#id40" id="id6">[10]</a>.</p>
</section>
<section id="api-design-and-implementation-revisions">
<h2><a class="toc-backref" href="#api-design-and-implementation-revisions" role="doc-backlink">API Design and Implementation Revisions</a></h2>
<ol class="arabic">
<li>Feedback on the initial beta release of Python 3.5 resulted in a
redesign of the object model supporting this PEP to more clearly
separate native coroutines from generators - rather than being a
new kind of generator, native coroutines are now their own
completely distinct type (implemented in <a class="footnote-reference brackets" href="#id47" id="id7">[17]</a>).<p>This change was implemented based primarily due to problems
encountered attempting to integrate support for native coroutines
into the Tornado web server (reported in <a class="footnote-reference brackets" href="#id48" id="id8">[18]</a>).</p>
</li>
<li>In CPython 3.5.2, the <code class="docutils literal notranslate"><span class="pre">__aiter__</span></code> protocol was updated.<p>Before 3.5.2, <code class="docutils literal notranslate"><span class="pre">__aiter__</span></code> was expected to return an <em>awaitable</em>
resolving to an <em>asynchronous iterator</em>. Starting with 3.5.2,
<code class="docutils literal notranslate"><span class="pre">__aiter__</span></code> should return asynchronous iterators directly.</p>
<p>If the old protocol is used in 3.5.2, Python will raise a
<code class="docutils literal notranslate"><span class="pre">PendingDeprecationWarning</span></code>.</p>
<p>In CPython 3.6, the old <code class="docutils literal notranslate"><span class="pre">__aiter__</span></code> protocol will still be
supported with a <code class="docutils literal notranslate"><span class="pre">DeprecationWarning</span></code> being raised.</p>
<p>In CPython 3.7, the old <code class="docutils literal notranslate"><span class="pre">__aiter__</span></code> protocol will no longer be
supported: a <code class="docutils literal notranslate"><span class="pre">RuntimeError</span></code> will be raised if <code class="docutils literal notranslate"><span class="pre">__aiter__</span></code>
returns anything but an asynchronous iterator.</p>
<p>See <a class="footnote-reference brackets" href="#id49" id="id9">[19]</a> and <a class="footnote-reference brackets" href="#id50" id="id10">[20]</a> for more details.</p>
</li>
</ol>
</section>
<section id="rationale-and-goals">
<h2><a class="toc-backref" href="#rationale-and-goals" role="doc-backlink">Rationale and Goals</a></h2>
<p>Current Python supports implementing coroutines via generators (PEP
342), further enhanced by the <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code> syntax introduced in PEP
380. This approach has a number of shortcomings:</p>
<ul class="simple">
<li>It is easy to confuse coroutines with regular generators, since they
share the same syntax; this is especially true for new developers.</li>
<li>Whether or not a function is a coroutine is determined by a presence
of <code class="docutils literal notranslate"><span class="pre">yield</span></code> or <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code> statements in its <em>body</em>, which can
lead to unobvious errors when such statements appear in or disappear
from function body during refactoring.</li>
<li>Support for asynchronous calls is limited to expressions where
<code class="docutils literal notranslate"><span class="pre">yield</span></code> is allowed syntactically, limiting the usefulness of
syntactic features, such as <code class="docutils literal notranslate"><span class="pre">with</span></code> and <code class="docutils literal notranslate"><span class="pre">for</span></code> statements.</li>
</ul>
<p>This proposal makes coroutines a native Python language feature, and
clearly separates them from generators. This removes
generator/coroutine ambiguity, and makes it possible to reliably define
coroutines without reliance on a specific library. This also enables
linters and IDEs to improve static code analysis and refactoring.</p>
<p>Native coroutines and the associated new syntax features make it
possible to define context manager and iteration protocols in
asynchronous terms. As shown later in this proposal, the new <code class="docutils literal notranslate"><span class="pre">async</span>
<span class="pre">with</span></code> statement lets Python programs perform asynchronous calls when
entering and exiting a runtime context, and the new <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">for</span></code>
statement makes it possible to perform asynchronous calls in iterators.</p>
</section>
<section id="specification">
<h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
<p>This proposal introduces new syntax and semantics to enhance coroutine
support in Python.</p>
<p>This specification presumes knowledge of the implementation of
coroutines in Python (<a class="pep reference internal" href="../pep-0342/" title="PEP 342 Coroutines via Enhanced Generators">PEP 342</a> and <a class="pep reference internal" href="../pep-0380/" title="PEP 380 Syntax for Delegating to a Subgenerator">PEP 380</a>). Motivation for the syntax
changes proposed here comes from the asyncio framework (<a class="pep reference internal" href="../pep-3156/" title="PEP 3156 Asynchronous IO Support Rebooted: the “asyncio” Module">PEP 3156</a>) and
the “Cofunctions” proposal (<a class="pep reference internal" href="../pep-3152/" title="PEP 3152 Cofunctions">PEP 3152</a>, now rejected in favor of this
specification).</p>
<p>From this point in this document we use the word <em>native coroutine</em> to
refer to functions declared using the new syntax. <em>generator-based
coroutine</em> is used where necessary to refer to coroutines that are
based on generator syntax. <em>coroutine</em> is used in contexts where both
definitions are applicable.</p>
<section id="new-coroutine-declaration-syntax">
<h3><a class="toc-backref" href="#new-coroutine-declaration-syntax" role="doc-backlink">New Coroutine Declaration Syntax</a></h3>
<p>The following new syntax is used to declare a <em>native coroutine</em>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">def</span> <span class="nf">read_data</span><span class="p">(</span><span class="n">db</span><span class="p">):</span>
<span class="k">pass</span>
</pre></div>
</div>
<p>Key properties of <em>coroutines</em>:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code> functions are always coroutines, even if they do not
contain <code class="docutils literal notranslate"><span class="pre">await</span></code> expressions.</li>
<li>It is a <code class="docutils literal notranslate"><span class="pre">SyntaxError</span></code> to have <code class="docutils literal notranslate"><span class="pre">yield</span></code> or <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code>
expressions in an <code class="docutils literal notranslate"><span class="pre">async</span></code> function.</li>
<li>Internally, two new code object flags were introduced:<ul>
<li><code class="docutils literal notranslate"><span class="pre">CO_COROUTINE</span></code> is used to mark <em>native coroutines</em>
(defined with new syntax).</li>
<li><code class="docutils literal notranslate"><span class="pre">CO_ITERABLE_COROUTINE</span></code> is used to make <em>generator-based
coroutines</em> compatible with <em>native coroutines</em> (set by
<a class="reference internal" href="#types-coroutine">types.coroutine()</a> function).</li>
</ul>
</li>
<li>Regular generators, when called, return a <em>generator object</em>;
similarly, coroutines return a <em>coroutine</em> object.</li>
<li><code class="docutils literal notranslate"><span class="pre">StopIteration</span></code> exceptions are not propagated out of coroutines,
and are replaced with a <code class="docutils literal notranslate"><span class="pre">RuntimeError</span></code>. For regular generators
such behavior requires a future import (see <a class="pep reference internal" href="../pep-0479/" title="PEP 479 Change StopIteration handling inside generators">PEP 479</a>).</li>
<li>When a <em>native coroutine</em> is garbage collected, a <code class="docutils literal notranslate"><span class="pre">RuntimeWarning</span></code>
is raised if it was never awaited on (see also
<a class="reference internal" href="#debugging-features">Debugging Features</a>).</li>
<li>See also <a class="reference internal" href="#coroutine-objects">Coroutine objects</a> section.</li>
</ul>
</section>
<section id="types-coroutine">
<h3><a class="toc-backref" href="#types-coroutine" role="doc-backlink">types.coroutine()</a></h3>
<p>A new function <code class="docutils literal notranslate"><span class="pre">coroutine(fn)</span></code> is added to the <code class="docutils literal notranslate"><span class="pre">types</span></code> module. It
allows interoperability between existing <em>generator-based coroutines</em>
in asyncio and <em>native coroutines</em> introduced by this PEP:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@types</span><span class="o">.</span><span class="n">coroutine</span>
<span class="k">def</span> <span class="nf">process_data</span><span class="p">(</span><span class="n">db</span><span class="p">):</span>
<span class="n">data</span> <span class="o">=</span> <span class="k">yield from</span> <span class="n">read_data</span><span class="p">(</span><span class="n">db</span><span class="p">)</span>
<span class="o">...</span>
</pre></div>
</div>
<p>The function applies <code class="docutils literal notranslate"><span class="pre">CO_ITERABLE_COROUTINE</span></code> flag to
generator-functions code object, making it return a <em>coroutine</em> object.</p>
<p>If <code class="docutils literal notranslate"><span class="pre">fn</span></code> is not a <em>generator function</em>, it is wrapped. If it returns
a <em>generator</em>, it will be wrapped in an <em>awaitable</em> proxy object
(see below the definition of awaitable objects).</p>
<p>Note, that the <code class="docutils literal notranslate"><span class="pre">CO_COROUTINE</span></code> flag is not applied by
<code class="docutils literal notranslate"><span class="pre">types.coroutine()</span></code> to make it possible to separate <em>native
coroutines</em> defined with new syntax, from <em>generator-based coroutines</em>.</p>
</section>
<section id="await-expression">
<h3><a class="toc-backref" href="#await-expression" role="doc-backlink">Await Expression</a></h3>
<p>The following new <code class="docutils literal notranslate"><span class="pre">await</span></code> expression is used to obtain a result of
coroutine execution:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">def</span> <span class="nf">read_data</span><span class="p">(</span><span class="n">db</span><span class="p">):</span>
<span class="n">data</span> <span class="o">=</span> <span class="k">await</span> <span class="n">db</span><span class="o">.</span><span class="n">fetch</span><span class="p">(</span><span class="s1">&#39;SELECT ...&#39;</span><span class="p">)</span>
<span class="o">...</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">await</span></code>, similarly to <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code>, suspends execution of
<code class="docutils literal notranslate"><span class="pre">read_data</span></code> coroutine until <code class="docutils literal notranslate"><span class="pre">db.fetch</span></code> <em>awaitable</em> completes and
returns the result data.</p>
<p>It uses the <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code> implementation with an extra step of
validating its argument. <code class="docutils literal notranslate"><span class="pre">await</span></code> only accepts an <em>awaitable</em>, which
can be one of:</p>
<ul>
<li>A <em>native coroutine</em> object returned from a <em>native coroutine
function</em>.</li>
<li>A <em>generator-based coroutine</em> object returned from a function
decorated with <code class="docutils literal notranslate"><span class="pre">types.coroutine()</span></code>.</li>
<li>An object with an <code class="docutils literal notranslate"><span class="pre">__await__</span></code> method returning an iterator.<p>Any <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code> chain of calls ends with a <code class="docutils literal notranslate"><span class="pre">yield</span></code>. This is a
fundamental mechanism of how <em>Futures</em> are implemented. Since,
internally, coroutines are a special kind of generators, every
<code class="docutils literal notranslate"><span class="pre">await</span></code> is suspended by a <code class="docutils literal notranslate"><span class="pre">yield</span></code> somewhere down the chain of
<code class="docutils literal notranslate"><span class="pre">await</span></code> calls (please refer to <a class="pep reference internal" href="../pep-3156/" title="PEP 3156 Asynchronous IO Support Rebooted: the “asyncio” Module">PEP 3156</a> for a detailed
explanation).</p>
<p>To enable this behavior for coroutines, a new magic method called
<code class="docutils literal notranslate"><span class="pre">__await__</span></code> is added. In asyncio, for instance, to enable <em>Future</em>
objects in <code class="docutils literal notranslate"><span class="pre">await</span></code> statements, the only change is to add
<code class="docutils literal notranslate"><span class="pre">__await__</span> <span class="pre">=</span> <span class="pre">__iter__</span></code> line to <code class="docutils literal notranslate"><span class="pre">asyncio.Future</span></code> class.</p>
<p>Objects with <code class="docutils literal notranslate"><span class="pre">__await__</span></code> method are called <em>Future-like</em> objects in
the rest of this PEP.</p>
<p>It is a <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> if <code class="docutils literal notranslate"><span class="pre">__await__</span></code> returns anything but an
iterator.</p>
</li>
<li>Objects defined with CPython C API with a <code class="docutils literal notranslate"><span class="pre">tp_as_async.am_await</span></code>
function, returning an <em>iterator</em> (similar to <code class="docutils literal notranslate"><span class="pre">__await__</span></code> method).</li>
</ul>
<p>It is a <code class="docutils literal notranslate"><span class="pre">SyntaxError</span></code> to use <code class="docutils literal notranslate"><span class="pre">await</span></code> outside of an <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code>
function (like it is a <code class="docutils literal notranslate"><span class="pre">SyntaxError</span></code> to use <code class="docutils literal notranslate"><span class="pre">yield</span></code> outside of
<code class="docutils literal notranslate"><span class="pre">def</span></code> function).</p>
<p>It is a <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> to pass anything other than an <em>awaitable</em> object
to an <code class="docutils literal notranslate"><span class="pre">await</span></code> expression.</p>
<section id="updated-operator-precedence-table">
<h4><a class="toc-backref" href="#updated-operator-precedence-table" role="doc-backlink">Updated operator precedence table</a></h4>
<p><code class="docutils literal notranslate"><span class="pre">await</span></code> keyword is defined as follows:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">power</span> <span class="p">:</span><span class="o">:=</span> <span class="k">await</span> <span class="p">[</span><span class="s2">&quot;**&quot;</span> <span class="n">u_expr</span><span class="p">]</span>
<span class="k">await</span> <span class="p">:</span><span class="o">:=</span> <span class="p">[</span><span class="s2">&quot;await&quot;</span><span class="p">]</span> <span class="n">primary</span>
</pre></div>
</div>
<p>where “primary” represents the most tightly bound operations of the
language. Its syntax is:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">primary</span> <span class="p">:</span><span class="o">:=</span> <span class="n">atom</span> <span class="o">|</span> <span class="n">attributeref</span> <span class="o">|</span> <span class="n">subscription</span> <span class="o">|</span> <span class="n">slicing</span> <span class="o">|</span> <span class="n">call</span>
</pre></div>
</div>
<p>See Python Documentation <a class="footnote-reference brackets" href="#id42" id="id11">[12]</a> and <a class="reference internal" href="#grammar-updates">Grammar Updates</a> section of this
proposal for details.</p>
<p>The key <code class="docutils literal notranslate"><span class="pre">await</span></code> difference from <code class="docutils literal notranslate"><span class="pre">yield</span></code> and <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code>
operators is that <em>await expressions</em> do not require parentheses around
them most of the times.</p>
<p>Also, <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code> allows any expression as its argument, including
expressions like <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span> <span class="pre">a()</span> <span class="pre">+</span> <span class="pre">b()</span></code>, that would be parsed as
<code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span> <span class="pre">(a()</span> <span class="pre">+</span> <span class="pre">b())</span></code>, which is almost always a bug. In general,
the result of any arithmetic operation is not an <em>awaitable</em> object.
To avoid this kind of mistakes, it was decided to make <code class="docutils literal notranslate"><span class="pre">await</span></code>
precedence lower than <code class="docutils literal notranslate"><span class="pre">[]</span></code>, <code class="docutils literal notranslate"><span class="pre">()</span></code>, and <code class="docutils literal notranslate"><span class="pre">.</span></code>, but higher than <code class="docutils literal notranslate"><span class="pre">**</span></code>
operators.</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head">Operator</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">yield</span></code> <code class="docutils literal notranslate"><span class="pre">x</span></code>,
<code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code> <code class="docutils literal notranslate"><span class="pre">x</span></code></td>
<td>Yield expression</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">lambda</span></code></td>
<td>Lambda expression</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">if</span></code> <code class="docutils literal notranslate"><span class="pre">else</span></code></td>
<td>Conditional expression</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">or</span></code></td>
<td>Boolean OR</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">and</span></code></td>
<td>Boolean AND</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">not</span></code> <code class="docutils literal notranslate"><span class="pre">x</span></code></td>
<td>Boolean NOT</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">in</span></code>, <code class="docutils literal notranslate"><span class="pre">not</span> <span class="pre">in</span></code>,
<code class="docutils literal notranslate"><span class="pre">is</span></code>, <code class="docutils literal notranslate"><span class="pre">is</span> <span class="pre">not</span></code>, <code class="docutils literal notranslate"><span class="pre">&lt;</span></code>,
<code class="docutils literal notranslate"><span class="pre">&lt;=</span></code>, <code class="docutils literal notranslate"><span class="pre">&gt;</span></code>, <code class="docutils literal notranslate"><span class="pre">&gt;=</span></code>,
<code class="docutils literal notranslate"><span class="pre">!=</span></code>, <code class="docutils literal notranslate"><span class="pre">==</span></code></td>
<td>Comparisons, including membership
tests and identity tests</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">|</span></code></td>
<td>Bitwise OR</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">^</span></code></td>
<td>Bitwise XOR</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">&amp;</span></code></td>
<td>Bitwise AND</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">&lt;&lt;</span></code>, <code class="docutils literal notranslate"><span class="pre">&gt;&gt;</span></code></td>
<td>Shifts</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">+</span></code>, <code class="docutils literal notranslate"><span class="pre">-</span></code></td>
<td>Addition and subtraction</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">*</span></code>, <code class="docutils literal notranslate"><span class="pre">&#64;</span></code>, <code class="docutils literal notranslate"><span class="pre">/</span></code>, <code class="docutils literal notranslate"><span class="pre">//</span></code>,
<code class="docutils literal notranslate"><span class="pre">%</span></code></td>
<td>Multiplication, matrix
multiplication, division,
remainder</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">+x</span></code>, <code class="docutils literal notranslate"><span class="pre">-x</span></code>, <code class="docutils literal notranslate"><span class="pre">~x</span></code></td>
<td>Positive, negative, bitwise NOT</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">**</span></code></td>
<td>Exponentiation</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">await</span></code> <code class="docutils literal notranslate"><span class="pre">x</span></code></td>
<td>Await expression</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">x[index]</span></code>,
<code class="docutils literal notranslate"><span class="pre">x[index:index]</span></code>,
<code class="docutils literal notranslate"><span class="pre">x(arguments...)</span></code>,
<code class="docutils literal notranslate"><span class="pre">x.attribute</span></code></td>
<td>Subscription, slicing,
call, attribute reference</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">(expressions...)</span></code>,
<code class="docutils literal notranslate"><span class="pre">[expressions...]</span></code>,
<code class="docutils literal notranslate"><span class="pre">{key:</span> <span class="pre">value...}</span></code>,
<code class="docutils literal notranslate"><span class="pre">{expressions...}</span></code></td>
<td>Binding or tuple display,
list display,
dictionary display,
set display</td>
</tr>
</tbody>
</table>
</section>
<section id="examples-of-await-expressions">
<h4><a class="toc-backref" href="#examples-of-await-expressions" role="doc-backlink">Examples of “await” expressions</a></h4>
<p>Valid syntax examples:</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head">Expression</th>
<th class="head">Will be parsed as</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">if</span> <span class="pre">await</span> <span class="pre">fut:</span> <span class="pre">pass</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">if</span> <span class="pre">(await</span> <span class="pre">fut):</span> <span class="pre">pass</span></code></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">if</span> <span class="pre">await</span> <span class="pre">fut</span> <span class="pre">+</span> <span class="pre">1:</span> <span class="pre">pass</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">if</span> <span class="pre">(await</span> <span class="pre">fut)</span> <span class="pre">+</span> <span class="pre">1:</span> <span class="pre">pass</span></code></td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">pair</span> <span class="pre">=</span> <span class="pre">await</span> <span class="pre">fut,</span> <span class="pre">'spam'</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">pair</span> <span class="pre">=</span> <span class="pre">(await</span> <span class="pre">fut),</span> <span class="pre">'spam'</span></code></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">with</span> <span class="pre">await</span> <span class="pre">fut,</span> <span class="pre">open():</span> <span class="pre">pass</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">with</span> <span class="pre">(await</span> <span class="pre">fut),</span> <span class="pre">open():</span> <span class="pre">pass</span></code></td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">await</span> <span class="pre">foo()['spam'].baz()()</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">await</span> <span class="pre">(</span> <span class="pre">foo()['spam'].baz()()</span> <span class="pre">)</span></code></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">return</span> <span class="pre">await</span> <span class="pre">coro()</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">return</span> <span class="pre">(</span> <span class="pre">await</span> <span class="pre">coro()</span> <span class="pre">)</span></code></td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">res</span> <span class="pre">=</span> <span class="pre">await</span> <span class="pre">coro()</span> <span class="pre">**</span> <span class="pre">2</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">res</span> <span class="pre">=</span> <span class="pre">(await</span> <span class="pre">coro())</span> <span class="pre">**</span> <span class="pre">2</span></code></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">func(a1=await</span> <span class="pre">coro(),</span> <span class="pre">a2=0)</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">func(a1=(await</span> <span class="pre">coro()),</span> <span class="pre">a2=0)</span></code></td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">await</span> <span class="pre">foo()</span> <span class="pre">+</span> <span class="pre">await</span> <span class="pre">bar()</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">(await</span> <span class="pre">foo())</span> <span class="pre">+</span> <span class="pre">(await</span> <span class="pre">bar())</span></code></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">-await</span> <span class="pre">foo()</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">-(await</span> <span class="pre">foo())</span></code></td>
</tr>
</tbody>
</table>
<p>Invalid syntax examples:</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head">Expression</th>
<th class="head">Should be written as</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">await</span> <span class="pre">await</span> <span class="pre">coro()</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">await</span> <span class="pre">(await</span> <span class="pre">coro())</span></code></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">await</span> <span class="pre">-coro()</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">await</span> <span class="pre">(-coro())</span></code></td>
</tr>
</tbody>
</table>
</section>
</section>
<section id="asynchronous-context-managers-and-async-with">
<h3><a class="toc-backref" href="#asynchronous-context-managers-and-async-with" role="doc-backlink">Asynchronous Context Managers and “async with”</a></h3>
<p>An <em>asynchronous context manager</em> is a context manager that is able to
suspend execution in its <em>enter</em> and <em>exit</em> methods.</p>
<p>To make this possible, a new protocol for asynchronous context managers
is proposed. Two new magic methods are added: <code class="docutils literal notranslate"><span class="pre">__aenter__</span></code> and
<code class="docutils literal notranslate"><span class="pre">__aexit__</span></code>. Both must return an <em>awaitable</em>.</p>
<p>An example of an asynchronous context manager:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">AsyncContextManager</span><span class="p">:</span>
<span class="k">async</span> <span class="k">def</span> <span class="fm">__aenter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">await</span> <span class="n">log</span><span class="p">(</span><span class="s1">&#39;entering context&#39;</span><span class="p">)</span>
<span class="k">async</span> <span class="k">def</span> <span class="fm">__aexit__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exc_type</span><span class="p">,</span> <span class="n">exc</span><span class="p">,</span> <span class="n">tb</span><span class="p">):</span>
<span class="k">await</span> <span class="n">log</span><span class="p">(</span><span class="s1">&#39;exiting context&#39;</span><span class="p">)</span>
</pre></div>
</div>
<section id="new-syntax">
<h4><a class="toc-backref" href="#new-syntax" role="doc-backlink">New Syntax</a></h4>
<p>A new statement for asynchronous context managers is proposed:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">with</span> <span class="n">EXPR</span> <span class="k">as</span> <span class="n">VAR</span><span class="p">:</span>
<span class="n">BLOCK</span>
</pre></div>
</div>
<p>which is semantically equivalent to:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">mgr</span> <span class="o">=</span> <span class="p">(</span><span class="n">EXPR</span><span class="p">)</span>
<span class="n">aexit</span> <span class="o">=</span> <span class="nb">type</span><span class="p">(</span><span class="n">mgr</span><span class="p">)</span><span class="o">.</span><span class="fm">__aexit__</span>
<span class="n">aenter</span> <span class="o">=</span> <span class="nb">type</span><span class="p">(</span><span class="n">mgr</span><span class="p">)</span><span class="o">.</span><span class="fm">__aenter__</span>
<span class="n">VAR</span> <span class="o">=</span> <span class="k">await</span> <span class="n">aenter</span><span class="p">(</span><span class="n">mgr</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">BLOCK</span>
<span class="k">except</span><span class="p">:</span>
<span class="k">if</span> <span class="ow">not</span> <span class="k">await</span> <span class="n">aexit</span><span class="p">(</span><span class="n">mgr</span><span class="p">,</span> <span class="o">*</span><span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">()):</span>
<span class="k">raise</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">await</span> <span class="n">aexit</span><span class="p">(</span><span class="n">mgr</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
</pre></div>
</div>
<p>As with regular <code class="docutils literal notranslate"><span class="pre">with</span></code> statements, it is possible to specify multiple
context managers in a single <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">with</span></code> statement.</p>
<p>It is an error to pass a regular context manager without <code class="docutils literal notranslate"><span class="pre">__aenter__</span></code>
and <code class="docutils literal notranslate"><span class="pre">__aexit__</span></code> methods to <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">with</span></code>. It is a <code class="docutils literal notranslate"><span class="pre">SyntaxError</span></code>
to use <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">with</span></code> outside of an <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code> function.</p>
</section>
<section id="example">
<h4><a class="toc-backref" href="#example" role="doc-backlink">Example</a></h4>
<p>With <em>asynchronous context managers</em> it is easy to implement proper
database transaction managers for coroutines:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">def</span> <span class="nf">commit</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">data</span><span class="p">):</span>
<span class="o">...</span>
<span class="k">async</span> <span class="k">with</span> <span class="n">session</span><span class="o">.</span><span class="n">transaction</span><span class="p">():</span>
<span class="o">...</span>
<span class="k">await</span> <span class="n">session</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="o">...</span>
</pre></div>
</div>
<p>Code that needs locking also looks lighter:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">with</span> <span class="n">lock</span><span class="p">:</span>
<span class="o">...</span>
</pre></div>
</div>
<p>instead of:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">with</span> <span class="p">(</span><span class="k">yield from</span> <span class="n">lock</span><span class="p">):</span>
<span class="o">...</span>
</pre></div>
</div>
</section>
</section>
<section id="asynchronous-iterators-and-async-for">
<h3><a class="toc-backref" href="#asynchronous-iterators-and-async-for" role="doc-backlink">Asynchronous Iterators and “async for”</a></h3>
<p>An <em>asynchronous iterable</em> is able to call asynchronous code in its
<em>iter</em> implementation, and <em>asynchronous iterator</em> can call
asynchronous code in its <em>next</em> method. To support asynchronous
iteration:</p>
<ol class="arabic simple">
<li>An object must implement an <code class="docutils literal notranslate"><span class="pre">__aiter__</span></code> method (or, if defined
with CPython C API, <code class="docutils literal notranslate"><span class="pre">tp_as_async.am_aiter</span></code> slot) returning an
<em>asynchronous iterator object</em>.</li>
<li>An <em>asynchronous iterator object</em> must implement an <code class="docutils literal notranslate"><span class="pre">__anext__</span></code>
method (or, if defined with CPython C API, <code class="docutils literal notranslate"><span class="pre">tp_as_async.am_anext</span></code>
slot) returning an <em>awaitable</em>.</li>
<li>To stop iteration <code class="docutils literal notranslate"><span class="pre">__anext__</span></code> must raise a <code class="docutils literal notranslate"><span class="pre">StopAsyncIteration</span></code>
exception.</li>
</ol>
<p>An example of asynchronous iterable:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">AsyncIterable</span><span class="p">:</span>
<span class="k">def</span> <span class="fm">__aiter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span>
<span class="k">async</span> <span class="k">def</span> <span class="fm">__anext__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">data</span> <span class="o">=</span> <span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">fetch_data</span><span class="p">()</span>
<span class="k">if</span> <span class="n">data</span><span class="p">:</span>
<span class="k">return</span> <span class="n">data</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">StopAsyncIteration</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">fetch_data</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="o">...</span>
</pre></div>
</div>
<section id="id12">
<h4><a class="toc-backref" href="#id12" role="doc-backlink">New Syntax</a></h4>
<p>A new statement for iterating through asynchronous iterators is
proposed:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">for</span> <span class="n">TARGET</span> <span class="ow">in</span> <span class="n">ITER</span><span class="p">:</span>
<span class="n">BLOCK</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">BLOCK2</span>
</pre></div>
</div>
<p>which is semantically equivalent to:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">iter</span> <span class="o">=</span> <span class="p">(</span><span class="n">ITER</span><span class="p">)</span>
<span class="nb">iter</span> <span class="o">=</span> <span class="nb">type</span><span class="p">(</span><span class="nb">iter</span><span class="p">)</span><span class="o">.</span><span class="fm">__aiter__</span><span class="p">(</span><span class="nb">iter</span><span class="p">)</span>
<span class="n">running</span> <span class="o">=</span> <span class="kc">True</span>
<span class="k">while</span> <span class="n">running</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">TARGET</span> <span class="o">=</span> <span class="k">await</span> <span class="nb">type</span><span class="p">(</span><span class="nb">iter</span><span class="p">)</span><span class="o">.</span><span class="fm">__anext__</span><span class="p">(</span><span class="nb">iter</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">StopAsyncIteration</span><span class="p">:</span>
<span class="n">running</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">BLOCK</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">BLOCK2</span>
</pre></div>
</div>
<p>It is a <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> to pass a regular iterable without <code class="docutils literal notranslate"><span class="pre">__aiter__</span></code>
method to <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">for</span></code>. It is a <code class="docutils literal notranslate"><span class="pre">SyntaxError</span></code> to use <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">for</span></code>
outside of an <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code> function.</p>
<p>As for with regular <code class="docutils literal notranslate"><span class="pre">for</span></code> statement, <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">for</span></code> has an optional
<code class="docutils literal notranslate"><span class="pre">else</span></code> clause.</p>
</section>
<section id="example-1">
<h4><a class="toc-backref" href="#example-1" role="doc-backlink">Example 1</a></h4>
<p>With asynchronous iteration protocol it is possible to asynchronously
buffer data during iteration:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">for</span> <span class="n">data</span> <span class="ow">in</span> <span class="n">cursor</span><span class="p">:</span>
<span class="o">...</span>
</pre></div>
</div>
<p>Where <code class="docutils literal notranslate"><span class="pre">cursor</span></code> is an asynchronous iterator that prefetches <code class="docutils literal notranslate"><span class="pre">N</span></code> rows
of data from a database after every <code class="docutils literal notranslate"><span class="pre">N</span></code> iterations.</p>
<p>The following code illustrates new asynchronous iteration protocol:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Cursor</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="bp">self</span><span class="o">.</span><span class="n">buffer</span> <span class="o">=</span> <span class="n">collections</span><span class="o">.</span><span class="n">deque</span><span class="p">()</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">_prefetch</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="o">...</span>
<span class="k">def</span> <span class="fm">__aiter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span>
<span class="k">async</span> <span class="k">def</span> <span class="fm">__anext__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">buffer</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">buffer</span> <span class="o">=</span> <span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">_prefetch</span><span class="p">()</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">buffer</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">StopAsyncIteration</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">popleft</span><span class="p">()</span>
</pre></div>
</div>
<p>then the <code class="docutils literal notranslate"><span class="pre">Cursor</span></code> class can be used as follows:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">Cursor</span><span class="p">():</span>
<span class="nb">print</span><span class="p">(</span><span class="n">row</span><span class="p">)</span>
</pre></div>
</div>
<p>which would be equivalent to the following code:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">i</span> <span class="o">=</span> <span class="n">Cursor</span><span class="p">()</span><span class="o">.</span><span class="fm">__aiter__</span><span class="p">()</span>
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">row</span> <span class="o">=</span> <span class="k">await</span> <span class="n">i</span><span class="o">.</span><span class="fm">__anext__</span><span class="p">()</span>
<span class="k">except</span> <span class="ne">StopAsyncIteration</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">else</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="n">row</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="example-2">
<h4><a class="toc-backref" href="#example-2" role="doc-backlink">Example 2</a></h4>
<p>The following is a utility class that transforms a regular iterable to
an asynchronous one. While this is not a very useful thing to do, the
code illustrates the relationship between regular and asynchronous
iterators.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">AsyncIteratorWrapper</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">obj</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_it</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span>
<span class="k">def</span> <span class="fm">__aiter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span>
<span class="k">async</span> <span class="k">def</span> <span class="fm">__anext__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">value</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_it</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">StopIteration</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">StopAsyncIteration</span>
<span class="k">return</span> <span class="n">value</span>
<span class="k">async</span> <span class="k">for</span> <span class="n">letter</span> <span class="ow">in</span> <span class="n">AsyncIteratorWrapper</span><span class="p">(</span><span class="s2">&quot;abc&quot;</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="n">letter</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="why-stopasynciteration">
<h4><a class="toc-backref" href="#why-stopasynciteration" role="doc-backlink">Why StopAsyncIteration?</a></h4>
<p>Coroutines are still based on generators internally. So, before PEP
479, there was no fundamental difference between</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">g1</span><span class="p">():</span>
<span class="k">yield from</span> <span class="n">fut</span>
<span class="k">return</span> <span class="s1">&#39;spam&#39;</span>
</pre></div>
</div>
<p>and</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">g2</span><span class="p">():</span>
<span class="k">yield from</span> <span class="n">fut</span>
<span class="k">raise</span> <span class="ne">StopIteration</span><span class="p">(</span><span class="s1">&#39;spam&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>And since <a class="pep reference internal" href="../pep-0479/" title="PEP 479 Change StopIteration handling inside generators">PEP 479</a> is accepted and enabled by default for coroutines,
the following example will have its <code class="docutils literal notranslate"><span class="pre">StopIteration</span></code> wrapped into a
<code class="docutils literal notranslate"><span class="pre">RuntimeError</span></code></p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">def</span> <span class="nf">a1</span><span class="p">():</span>
<span class="k">await</span> <span class="n">fut</span>
<span class="k">raise</span> <span class="ne">StopIteration</span><span class="p">(</span><span class="s1">&#39;spam&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>The only way to tell the outside code that the iteration has ended is
to raise something other than <code class="docutils literal notranslate"><span class="pre">StopIteration</span></code>. Therefore, a new
built-in exception class <code class="docutils literal notranslate"><span class="pre">StopAsyncIteration</span></code> was added.</p>
<p>Moreover, with semantics from <a class="pep reference internal" href="../pep-0479/" title="PEP 479 Change StopIteration handling inside generators">PEP 479</a>, all <code class="docutils literal notranslate"><span class="pre">StopIteration</span></code> exceptions
raised in coroutines are wrapped in <code class="docutils literal notranslate"><span class="pre">RuntimeError</span></code>.</p>
</section>
</section>
<section id="coroutine-objects">
<h3><a class="toc-backref" href="#coroutine-objects" role="doc-backlink">Coroutine objects</a></h3>
<section id="differences-from-generators">
<h4><a class="toc-backref" href="#differences-from-generators" role="doc-backlink">Differences from generators</a></h4>
<p>This section applies only to <em>native coroutines</em> with <code class="docutils literal notranslate"><span class="pre">CO_COROUTINE</span></code>
flag, i.e. defined with the new <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code> syntax.</p>
<p><strong>The behavior of existing *generator-based coroutines* in asyncio
remains unchanged.</strong></p>
<p>Great effort has been made to make sure that coroutines and
generators are treated as distinct concepts:</p>
<ol class="arabic">
<li><em>Native coroutine</em> objects do not implement <code class="docutils literal notranslate"><span class="pre">__iter__</span></code> and
<code class="docutils literal notranslate"><span class="pre">__next__</span></code> methods. Therefore, they cannot be iterated over or
passed to <code class="docutils literal notranslate"><span class="pre">iter()</span></code>, <code class="docutils literal notranslate"><span class="pre">list()</span></code>, <code class="docutils literal notranslate"><span class="pre">tuple()</span></code> and other built-ins.
They also cannot be used in a <code class="docutils literal notranslate"><span class="pre">for..in</span></code> loop.<p>An attempt to use <code class="docutils literal notranslate"><span class="pre">__iter__</span></code> or <code class="docutils literal notranslate"><span class="pre">__next__</span></code> on a <em>native
coroutine</em> object will result in a <code class="docutils literal notranslate"><span class="pre">TypeError</span></code>.</p>
</li>
<li><em>Plain generators</em> cannot <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code> <em>native coroutines</em>:
doing so will result in a <code class="docutils literal notranslate"><span class="pre">TypeError</span></code>.</li>
<li><em>generator-based coroutines</em> (for asyncio code must be decorated
with <code class="docutils literal notranslate"><span class="pre">&#64;asyncio.coroutine</span></code> <a class="footnote-reference brackets" href="#id31" id="id13">[1]</a>) can <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code> <em>native coroutine
objects</em>.</li>
<li><code class="docutils literal notranslate"><span class="pre">inspect.isgenerator()</span></code> and <code class="docutils literal notranslate"><span class="pre">inspect.isgeneratorfunction()</span></code>
return <code class="docutils literal notranslate"><span class="pre">False</span></code> for <em>native coroutine</em> objects and <em>native
coroutine functions</em>.</li>
</ol>
</section>
<section id="coroutine-object-methods">
<h4><a class="toc-backref" href="#coroutine-object-methods" role="doc-backlink">Coroutine object methods</a></h4>
<p>Coroutines are based on generators internally, thus they share the
implementation. Similarly to generator objects, <em>coroutines</em> have
<code class="docutils literal notranslate"><span class="pre">throw()</span></code>, <code class="docutils literal notranslate"><span class="pre">send()</span></code> and <code class="docutils literal notranslate"><span class="pre">close()</span></code> methods. <code class="docutils literal notranslate"><span class="pre">StopIteration</span></code> and
<code class="docutils literal notranslate"><span class="pre">GeneratorExit</span></code> play the same role for coroutines (although
<a class="pep reference internal" href="../pep-0479/" title="PEP 479 Change StopIteration handling inside generators">PEP 479</a> is enabled by default for coroutines). See <a class="pep reference internal" href="../pep-0342/" title="PEP 342 Coroutines via Enhanced Generators">PEP 342</a>, <a class="pep reference internal" href="../pep-0380/" title="PEP 380 Syntax for Delegating to a Subgenerator">PEP 380</a>,
and Python Documentation <a class="footnote-reference brackets" href="#id41" id="id14">[11]</a> for details.</p>
<p><code class="docutils literal notranslate"><span class="pre">throw()</span></code>, <code class="docutils literal notranslate"><span class="pre">send()</span></code> methods for <em>coroutines</em> are used to push
values and raise errors into <em>Future-like</em> objects.</p>
</section>
</section>
<section id="debugging-features">
<h3><a class="toc-backref" href="#debugging-features" role="doc-backlink">Debugging Features</a></h3>
<p>A common beginner mistake is forgetting to use <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code> on
coroutines:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@asyncio</span><span class="o">.</span><span class="n">coroutine</span>
<span class="k">def</span> <span class="nf">useful</span><span class="p">():</span>
<span class="n">asyncio</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="c1"># this will do nothing without &#39;yield from&#39;</span>
</pre></div>
</div>
<p>For debugging this kind of mistakes there is a special debug mode in
asyncio, in which <code class="docutils literal notranslate"><span class="pre">&#64;coroutine</span></code> decorator wraps all functions with a
special object with a destructor logging a warning. Whenever a wrapped
generator gets garbage collected, a detailed logging message is
generated with information about where exactly the decorator function
was defined, stack trace of where it was collected, etc. Wrapper
object also provides a convenient <code class="docutils literal notranslate"><span class="pre">__repr__</span></code> function with detailed
information about the generator.</p>
<p>The only problem is how to enable these debug capabilities. Since
debug facilities should be a no-op in production mode, <code class="docutils literal notranslate"><span class="pre">&#64;coroutine</span></code>
decorator makes the decision of whether to wrap or not to wrap based on
an OS environment variable <code class="docutils literal notranslate"><span class="pre">PYTHONASYNCIODEBUG</span></code>. This way it is
possible to run asyncio programs with asyncios own functions
instrumented. <code class="docutils literal notranslate"><span class="pre">EventLoop.set_debug</span></code>, a different debug facility, has
no impact on <code class="docutils literal notranslate"><span class="pre">&#64;coroutine</span></code> decorators behavior.</p>
<p>With this proposal, coroutines is a native, distinct from generators,
concept. <em>In addition</em> to a <code class="docutils literal notranslate"><span class="pre">RuntimeWarning</span></code> being raised on
coroutines that were never awaited, it is proposed to add two new
functions to the <code class="docutils literal notranslate"><span class="pre">sys</span></code> module: <code class="docutils literal notranslate"><span class="pre">set_coroutine_wrapper</span></code> and
<code class="docutils literal notranslate"><span class="pre">get_coroutine_wrapper</span></code>. This is to enable advanced debugging
facilities in asyncio and other frameworks (such as displaying where
exactly coroutine was created, and a more detailed stack trace of where
it was garbage collected).</p>
</section>
<section id="new-standard-library-functions">
<h3><a class="toc-backref" href="#new-standard-library-functions" role="doc-backlink">New Standard Library Functions</a></h3>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">types.coroutine(gen)</span></code>. See <a class="reference internal" href="#types-coroutine">types.coroutine()</a> section for
details.</li>
<li><code class="docutils literal notranslate"><span class="pre">inspect.iscoroutine(obj)</span></code> returns <code class="docutils literal notranslate"><span class="pre">True</span></code> if <code class="docutils literal notranslate"><span class="pre">obj</span></code> is a
<em>native coroutine</em> object.</li>
<li><code class="docutils literal notranslate"><span class="pre">inspect.iscoroutinefunction(obj)</span></code> returns <code class="docutils literal notranslate"><span class="pre">True</span></code> if <code class="docutils literal notranslate"><span class="pre">obj</span></code> is a
<em>native coroutine function</em>.</li>
<li><code class="docutils literal notranslate"><span class="pre">inspect.isawaitable(obj)</span></code> returns <code class="docutils literal notranslate"><span class="pre">True</span></code> if <code class="docutils literal notranslate"><span class="pre">obj</span></code> is an
<em>awaitable</em>.</li>
<li><code class="docutils literal notranslate"><span class="pre">inspect.getcoroutinestate(coro)</span></code> returns the current state of
a <em>native coroutine object</em> (mirrors
<code class="docutils literal notranslate"><span class="pre">inspect.getfgeneratorstate(gen)</span></code>).</li>
<li><code class="docutils literal notranslate"><span class="pre">inspect.getcoroutinelocals(coro)</span></code> returns the mapping of a
<em>native coroutine objects</em> local variables to their values
(mirrors <code class="docutils literal notranslate"><span class="pre">inspect.getgeneratorlocals(gen)</span></code>).</li>
<li><code class="docutils literal notranslate"><span class="pre">sys.set_coroutine_wrapper(wrapper)</span></code> allows to intercept creation of
<em>native coroutine</em> objects. <code class="docutils literal notranslate"><span class="pre">wrapper</span></code> must be either a callable that
accepts one argument (a <em>coroutine</em> object), or <code class="docutils literal notranslate"><span class="pre">None</span></code>. <code class="docutils literal notranslate"><span class="pre">None</span></code>
resets the wrapper. If called twice, the new wrapper replaces the
previous one. The function is thread-specific. See <a class="reference internal" href="#debugging-features">Debugging
Features</a> for more details.</li>
<li><code class="docutils literal notranslate"><span class="pre">sys.get_coroutine_wrapper()</span></code> returns the current wrapper object.
Returns <code class="docutils literal notranslate"><span class="pre">None</span></code> if no wrapper was set. The function is
thread-specific. See <a class="reference internal" href="#debugging-features">Debugging Features</a> for more details.</li>
</ul>
</section>
<section id="new-abstract-base-classes">
<h3><a class="toc-backref" href="#new-abstract-base-classes" role="doc-backlink">New Abstract Base Classes</a></h3>
<p>In order to allow better integration with existing frameworks (such as
Tornado, see <a class="footnote-reference brackets" href="#id43" id="id15">[13]</a>) and compilers (such as Cython, see <a class="footnote-reference brackets" href="#id46" id="id16">[16]</a>), two new
Abstract Base Classes (ABC) are added:</p>
<ul>
<li><code class="docutils literal notranslate"><span class="pre">collections.abc.Awaitable</span></code> ABC for <em>Future-like</em> classes, that
implement <code class="docutils literal notranslate"><span class="pre">__await__</span></code> method.</li>
<li><code class="docutils literal notranslate"><span class="pre">collections.abc.Coroutine</span></code> ABC for <em>coroutine</em> objects, that
implement <code class="docutils literal notranslate"><span class="pre">send(value)</span></code>, <code class="docutils literal notranslate"><span class="pre">throw(type,</span> <span class="pre">exc,</span> <span class="pre">tb)</span></code>, <code class="docutils literal notranslate"><span class="pre">close()</span></code> and
<code class="docutils literal notranslate"><span class="pre">__await__()</span></code> methods.<p>Note that generator-based coroutines with <code class="docutils literal notranslate"><span class="pre">CO_ITERABLE_COROUTINE</span></code>
flag do not implement <code class="docutils literal notranslate"><span class="pre">__await__</span></code> method, and therefore are not
instances of <code class="docutils literal notranslate"><span class="pre">collections.abc.Coroutine</span></code> and
<code class="docutils literal notranslate"><span class="pre">collections.abc.Awaitable</span></code> ABCs:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@types</span><span class="o">.</span><span class="n">coroutine</span>
<span class="k">def</span> <span class="nf">gencoro</span><span class="p">():</span>
<span class="k">yield</span>
<span class="k">assert</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">gencoro</span><span class="p">(),</span> <span class="n">collections</span><span class="o">.</span><span class="n">abc</span><span class="o">.</span><span class="n">Coroutine</span><span class="p">)</span>
<span class="c1"># however:</span>
<span class="k">assert</span> <span class="n">inspect</span><span class="o">.</span><span class="n">isawaitable</span><span class="p">(</span><span class="n">gencoro</span><span class="p">())</span>
</pre></div>
</div>
</li>
</ul>
<p>To allow easy testing if objects support asynchronous iteration, two
more ABCs are added:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">collections.abc.AsyncIterable</span></code> tests for <code class="docutils literal notranslate"><span class="pre">__aiter__</span></code> method.</li>
<li><code class="docutils literal notranslate"><span class="pre">collections.abc.AsyncIterator</span></code> tests for <code class="docutils literal notranslate"><span class="pre">__aiter__</span></code> and
<code class="docutils literal notranslate"><span class="pre">__anext__</span></code> methods.</li>
</ul>
</section>
</section>
<section id="glossary">
<h2><a class="toc-backref" href="#glossary" role="doc-backlink">Glossary</a></h2>
<dl class="simple">
<dt>Native coroutine function</dt><dd>A coroutine function is declared with <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code>. It uses
<code class="docutils literal notranslate"><span class="pre">await</span></code> and <code class="docutils literal notranslate"><span class="pre">return</span> <span class="pre">value</span></code>; see <a class="reference internal" href="#new-coroutine-declaration-syntax">New Coroutine Declaration
Syntax</a> for details.</dd>
<dt>Native coroutine</dt><dd>Returned from a native coroutine function. See <a class="reference internal" href="#await-expression">Await Expression</a>
for details.</dd>
<dt>Generator-based coroutine function</dt><dd>Coroutines based on generator syntax. Most common example are
functions decorated with <code class="docutils literal notranslate"><span class="pre">&#64;asyncio.coroutine</span></code>.</dd>
<dt>Generator-based coroutine</dt><dd>Returned from a generator-based coroutine function.</dd>
<dt>Coroutine</dt><dd>Either <em>native coroutine</em> or <em>generator-based coroutine</em>.</dd>
<dt>Coroutine object</dt><dd>Either <em>native coroutine</em> object or <em>generator-based coroutine</em>
object.</dd>
<dt>Future-like object</dt><dd>An object with an <code class="docutils literal notranslate"><span class="pre">__await__</span></code> method, or a C object with
<code class="docutils literal notranslate"><span class="pre">tp_as_async-&gt;am_await</span></code> function, returning an <em>iterator</em>. Can be
consumed by an <code class="docutils literal notranslate"><span class="pre">await</span></code> expression in a coroutine. A coroutine
waiting for a Future-like object is suspended until the Future-like
objects <code class="docutils literal notranslate"><span class="pre">__await__</span></code> completes, and returns the result. See
<a class="reference internal" href="#await-expression">Await Expression</a> for details.</dd>
<dt>Awaitable</dt><dd>A <em>Future-like</em> object or a <em>coroutine</em> object. See <a class="reference internal" href="#await-expression">Await
Expression</a> for details.</dd>
<dt>Asynchronous context manager</dt><dd>An asynchronous context manager has <code class="docutils literal notranslate"><span class="pre">__aenter__</span></code> and <code class="docutils literal notranslate"><span class="pre">__aexit__</span></code>
methods and can be used with <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">with</span></code>. See <a class="reference internal" href="#asynchronous-context-managers-and-async-with">Asynchronous
Context Managers and “async with”</a> for details.</dd>
<dt>Asynchronous iterable</dt><dd>An object with an <code class="docutils literal notranslate"><span class="pre">__aiter__</span></code> method, which must return an
<em>asynchronous iterator</em> object. Can be used with <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">for</span></code>.
See <a class="reference internal" href="#asynchronous-iterators-and-async-for">Asynchronous Iterators and “async for”</a> for details.</dd>
<dt>Asynchronous iterator</dt><dd>An asynchronous iterator has an <code class="docutils literal notranslate"><span class="pre">__anext__</span></code> method. See
<a class="reference internal" href="#asynchronous-iterators-and-async-for">Asynchronous Iterators and “async for”</a> for details.</dd>
</dl>
</section>
<section id="transition-plan">
<h2><a class="toc-backref" href="#transition-plan" role="doc-backlink">Transition Plan</a></h2>
<p>To avoid backwards compatibility issues with <code class="docutils literal notranslate"><span class="pre">async</span></code> and <code class="docutils literal notranslate"><span class="pre">await</span></code>
keywords, it was decided to modify <code class="docutils literal notranslate"><span class="pre">tokenizer.c</span></code> in such a way, that
it:</p>
<ul class="simple">
<li>recognizes <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code> <code class="docutils literal notranslate"><span class="pre">NAME</span></code> tokens combination;</li>
<li>while tokenizing <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code> block, it replaces <code class="docutils literal notranslate"><span class="pre">'async'</span></code>
<code class="docutils literal notranslate"><span class="pre">NAME</span></code> token with <code class="docutils literal notranslate"><span class="pre">ASYNC</span></code>, and <code class="docutils literal notranslate"><span class="pre">'await'</span></code> <code class="docutils literal notranslate"><span class="pre">NAME</span></code> token with
<code class="docutils literal notranslate"><span class="pre">AWAIT</span></code>;</li>
<li>while tokenizing <code class="docutils literal notranslate"><span class="pre">def</span></code> block, it yields <code class="docutils literal notranslate"><span class="pre">'async'</span></code> and <code class="docutils literal notranslate"><span class="pre">'await'</span></code>
<code class="docutils literal notranslate"><span class="pre">NAME</span></code> tokens as is.</li>
</ul>
<p>This approach allows for seamless combination of new syntax features
(all of them available only in <code class="docutils literal notranslate"><span class="pre">async</span></code> functions) with any existing
code.</p>
<p>An example of having “async def” and “async” attribute in one piece of
code:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Spam</span><span class="p">:</span>
<span class="k">async</span> <span class="o">=</span> <span class="mi">42</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">ham</span><span class="p">():</span>
<span class="nb">print</span><span class="p">(</span><span class="nb">getattr</span><span class="p">(</span><span class="n">Spam</span><span class="p">,</span> <span class="s1">&#39;async&#39;</span><span class="p">))</span>
<span class="c1"># The coroutine can be executed and will print &#39;42&#39;</span>
</pre></div>
</div>
<section id="backwards-compatibility">
<h3><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards Compatibility</a></h3>
<p>This proposal preserves 100% backwards compatibility.</p>
<section id="asyncio">
<h4><a class="toc-backref" href="#asyncio" role="doc-backlink">asyncio</a></h4>
<p><code class="docutils literal notranslate"><span class="pre">asyncio</span></code> module was adapted and tested to work with coroutines and
new statements. Backwards compatibility is 100% preserved, i.e. all
existing code will work as-is.</p>
<p>The required changes are mainly:</p>
<ol class="arabic simple">
<li>Modify <code class="docutils literal notranslate"><span class="pre">&#64;asyncio.coroutine</span></code> decorator to use new
<code class="docutils literal notranslate"><span class="pre">types.coroutine()</span></code> function.</li>
<li>Add <code class="docutils literal notranslate"><span class="pre">__await__</span> <span class="pre">=</span> <span class="pre">__iter__</span></code> line to <code class="docutils literal notranslate"><span class="pre">asyncio.Future</span></code> class.</li>
<li>Add <code class="docutils literal notranslate"><span class="pre">ensure_future()</span></code> as an alias for <code class="docutils literal notranslate"><span class="pre">async()</span></code> function.
Deprecate <code class="docutils literal notranslate"><span class="pre">async()</span></code> function.</li>
</ol>
</section>
<section id="asyncio-migration-strategy">
<h4><a class="toc-backref" href="#asyncio-migration-strategy" role="doc-backlink">asyncio migration strategy</a></h4>
<p>Because <em>plain generators</em> cannot <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code> <em>native coroutine
objects</em> (see <a class="reference internal" href="#differences-from-generators">Differences from generators</a> section for more details),
it is advised to make sure that all generator-based coroutines are
decorated with <code class="docutils literal notranslate"><span class="pre">&#64;asyncio.coroutine</span></code> <em>before</em> starting to use the new
syntax.</p>
</section>
<section id="async-await-in-cpython-code-base">
<h4><a class="toc-backref" href="#async-await-in-cpython-code-base" role="doc-backlink">async/await in CPython code base</a></h4>
<p>There is no use of <code class="docutils literal notranslate"><span class="pre">await</span></code> names in CPython.</p>
<p><code class="docutils literal notranslate"><span class="pre">async</span></code> is mostly used by asyncio. We are addressing this by
renaming <code class="docutils literal notranslate"><span class="pre">async()</span></code> function to <code class="docutils literal notranslate"><span class="pre">ensure_future()</span></code> (see <a class="reference internal" href="#asyncio">asyncio</a>
section for details).</p>
<p>Another use of <code class="docutils literal notranslate"><span class="pre">async</span></code> keyword is in <code class="docutils literal notranslate"><span class="pre">Lib/xml/dom/xmlbuilder.py</span></code>,
to define an <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">=</span> <span class="pre">False</span></code> attribute for <code class="docutils literal notranslate"><span class="pre">DocumentLS</span></code> class.
There is no documentation or tests for it, it is not used anywhere else
in CPython. It is replaced with a getter, that raises a
<code class="docutils literal notranslate"><span class="pre">DeprecationWarning</span></code>, advising to use <code class="docutils literal notranslate"><span class="pre">async_</span></code> attribute instead.
async attribute is not documented and is not used in CPython code
base.</p>
</section>
</section>
<section id="grammar-updates">
<h3><a class="toc-backref" href="#grammar-updates" role="doc-backlink">Grammar Updates</a></h3>
<p>Grammar changes are fairly minimal:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">decorated</span><span class="p">:</span> <span class="n">decorators</span> <span class="p">(</span><span class="n">classdef</span> <span class="o">|</span> <span class="n">funcdef</span> <span class="o">|</span> <span class="n">async_funcdef</span><span class="p">)</span>
<span class="n">async_funcdef</span><span class="p">:</span> <span class="n">ASYNC</span> <span class="n">funcdef</span>
<span class="n">compound_stmt</span><span class="p">:</span> <span class="p">(</span><span class="n">if_stmt</span> <span class="o">|</span> <span class="n">while_stmt</span> <span class="o">|</span> <span class="n">for_stmt</span> <span class="o">|</span> <span class="n">try_stmt</span> <span class="o">|</span> <span class="n">with_stmt</span>
<span class="o">|</span> <span class="n">funcdef</span> <span class="o">|</span> <span class="n">classdef</span> <span class="o">|</span> <span class="n">decorated</span> <span class="o">|</span> <span class="n">async_stmt</span><span class="p">)</span>
<span class="n">async_stmt</span><span class="p">:</span> <span class="n">ASYNC</span> <span class="p">(</span><span class="n">funcdef</span> <span class="o">|</span> <span class="n">with_stmt</span> <span class="o">|</span> <span class="n">for_stmt</span><span class="p">)</span>
<span class="n">power</span><span class="p">:</span> <span class="n">atom_expr</span> <span class="p">[</span><span class="s1">&#39;**&#39;</span> <span class="n">factor</span><span class="p">]</span>
<span class="n">atom_expr</span><span class="p">:</span> <span class="p">[</span><span class="n">AWAIT</span><span class="p">]</span> <span class="n">atom</span> <span class="n">trailer</span><span class="o">*</span>
</pre></div>
</div>
</section>
<section id="deprecation-plans">
<h3><a class="toc-backref" href="#deprecation-plans" role="doc-backlink">Deprecation Plans</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">async</span></code> and <code class="docutils literal notranslate"><span class="pre">await</span></code> names will be softly deprecated in CPython 3.5
and 3.6. In 3.7 we will transform them to proper keywords. Making
<code class="docutils literal notranslate"><span class="pre">async</span></code> and <code class="docutils literal notranslate"><span class="pre">await</span></code> proper keywords before 3.7 might make it harder
for people to port their code to Python 3.</p>
</section>
</section>
<section id="design-considerations">
<h2><a class="toc-backref" href="#design-considerations" role="doc-backlink">Design Considerations</a></h2>
<section id="pep-3152">
<h3><a class="toc-backref" href="#pep-3152" role="doc-backlink">PEP 3152</a></h3>
<p><a class="pep reference internal" href="../pep-3152/" title="PEP 3152 Cofunctions">PEP 3152</a> by Gregory Ewing proposes a different mechanism for coroutines
(called “cofunctions”). Some key points:</p>
<ol class="arabic">
<li>A new keyword <code class="docutils literal notranslate"><span class="pre">codef</span></code> to declare a <em>cofunction</em>. <em>Cofunction</em> is
always a generator, even if there is no <code class="docutils literal notranslate"><span class="pre">cocall</span></code> expressions
inside it. Maps to <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code> in this proposal.</li>
<li>A new keyword <code class="docutils literal notranslate"><span class="pre">cocall</span></code> to call a <em>cofunction</em>. Can only be used
inside a <em>cofunction</em>. Maps to <code class="docutils literal notranslate"><span class="pre">await</span></code> in this proposal (with
some differences, see below).</li>
<li>It is not possible to call a <em>cofunction</em> without a <code class="docutils literal notranslate"><span class="pre">cocall</span></code>
keyword.</li>
<li><code class="docutils literal notranslate"><span class="pre">cocall</span></code> grammatically requires parentheses after it:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">atom</span><span class="p">:</span> <span class="n">cocall</span> <span class="o">|</span> <span class="o">&lt;</span><span class="n">existing</span> <span class="n">alternatives</span> <span class="k">for</span> <span class="n">atom</span><span class="o">&gt;</span>
<span class="n">cocall</span><span class="p">:</span> <span class="s1">&#39;cocall&#39;</span> <span class="n">atom</span> <span class="n">cotrailer</span><span class="o">*</span> <span class="s1">&#39;(&#39;</span> <span class="p">[</span><span class="n">arglist</span><span class="p">]</span> <span class="s1">&#39;)&#39;</span>
<span class="n">cotrailer</span><span class="p">:</span> <span class="s1">&#39;[&#39;</span> <span class="n">subscriptlist</span> <span class="s1">&#39;]&#39;</span> <span class="o">|</span> <span class="s1">&#39;.&#39;</span> <span class="n">NAME</span>
</pre></div>
</div>
</li>
<li><code class="docutils literal notranslate"><span class="pre">cocall</span> <span class="pre">f(*args,</span> <span class="pre">**kwds)</span></code> is semantically equivalent to
<code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span> <span class="pre">f.__cocall__(*args,</span> <span class="pre">**kwds)</span></code>.</li>
</ol>
<p>Differences from this proposal:</p>
<ol class="arabic">
<li>There is no equivalent of <code class="docutils literal notranslate"><span class="pre">__cocall__</span></code> in this PEP, which is
called and its result is passed to <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code> in the <code class="docutils literal notranslate"><span class="pre">cocall</span></code>
expression. <code class="docutils literal notranslate"><span class="pre">await</span></code> keyword expects an <em>awaitable</em> object,
validates the type, and executes <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code> on it. Although,
<code class="docutils literal notranslate"><span class="pre">__await__</span></code> method is similar to <code class="docutils literal notranslate"><span class="pre">__cocall__</span></code>, but is only used
to define <em>Future-like</em> objects.</li>
<li><code class="docutils literal notranslate"><span class="pre">await</span></code> is defined in almost the same way as <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code> in the
grammar (it is later enforced that <code class="docutils literal notranslate"><span class="pre">await</span></code> can only be inside
<code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code>). It is possible to simply write <code class="docutils literal notranslate"><span class="pre">await</span> <span class="pre">future</span></code>,
whereas <code class="docutils literal notranslate"><span class="pre">cocall</span></code> always requires parentheses.</li>
<li>To make asyncio work with <a class="pep reference internal" href="../pep-3152/" title="PEP 3152 Cofunctions">PEP 3152</a> it would be required to modify
<code class="docutils literal notranslate"><span class="pre">&#64;asyncio.coroutine</span></code> decorator to wrap all functions in an object
with a <code class="docutils literal notranslate"><span class="pre">__cocall__</span></code> method, or to implement <code class="docutils literal notranslate"><span class="pre">__cocall__</span></code> on
generators. To call <em>cofunctions</em> from existing generator-based
coroutines it would be required to use <code class="docutils literal notranslate"><span class="pre">costart(cofunc,</span> <span class="pre">*args,</span>
<span class="pre">**kwargs)</span></code> built-in.</li>
<li>Since it is impossible to call a <em>cofunction</em> without a <code class="docutils literal notranslate"><span class="pre">cocall</span></code>
keyword, it automatically prevents the common mistake of forgetting
to use <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code> on generator-based coroutines. This proposal
addresses this problem with a different approach, see <a class="reference internal" href="#debugging-features">Debugging
Features</a>.</li>
<li>A shortcoming of requiring a <code class="docutils literal notranslate"><span class="pre">cocall</span></code> keyword to call a coroutine
is that if is decided to implement coroutine-generators
coroutines with <code class="docutils literal notranslate"><span class="pre">yield</span></code> or <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">yield</span></code> expressions we
wouldnt need a <code class="docutils literal notranslate"><span class="pre">cocall</span></code> keyword to call them. So well end up
having <code class="docutils literal notranslate"><span class="pre">__cocall__</span></code> and no <code class="docutils literal notranslate"><span class="pre">__call__</span></code> for regular coroutines,
and having <code class="docutils literal notranslate"><span class="pre">__call__</span></code> and no <code class="docutils literal notranslate"><span class="pre">__cocall__</span></code> for
coroutine-generators.</li>
<li>Requiring parentheses grammatically also introduces a whole lot
of new problems.<p>The following code:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">await</span> <span class="n">fut</span>
<span class="k">await</span> <span class="n">function_returning_future</span><span class="p">()</span>
<span class="k">await</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">gather</span><span class="p">(</span><span class="n">coro1</span><span class="p">(</span><span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">),</span> <span class="n">coro2</span><span class="p">(</span><span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">))</span>
</pre></div>
</div>
<p>would look like:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">cocall</span> <span class="n">fut</span><span class="p">()</span> <span class="c1"># or cocall costart(fut)</span>
<span class="n">cocall</span> <span class="p">(</span><span class="n">function_returning_future</span><span class="p">())()</span>
<span class="n">cocall</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">gather</span><span class="p">(</span><span class="n">costart</span><span class="p">(</span><span class="n">coro1</span><span class="p">,</span> <span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">),</span>
<span class="n">costart</span><span class="p">(</span><span class="n">coro2</span><span class="p">,</span> <span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">))</span>
</pre></div>
</div>
</li>
<li>There are no equivalents of <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">for</span></code> and <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">with</span></code> in PEP
3152.</li>
</ol>
</section>
<section id="coroutine-generators">
<h3><a class="toc-backref" href="#coroutine-generators" role="doc-backlink">Coroutine-generators</a></h3>
<p>With <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">for</span></code> keyword it is desirable to have a concept of a
<em>coroutine-generator</em> a coroutine with <code class="docutils literal notranslate"><span class="pre">yield</span></code> and <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code>
expressions. To avoid any ambiguity with regular generators, we would
likely require to have an <code class="docutils literal notranslate"><span class="pre">async</span></code> keyword before <code class="docutils literal notranslate"><span class="pre">yield</span></code>, and
<code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">yield</span> <span class="pre">from</span></code> would raise a <code class="docutils literal notranslate"><span class="pre">StopAsyncIteration</span></code> exception.</p>
<p>While it is possible to implement coroutine-generators, we believe that
they are out of scope of this proposal. It is an advanced concept that
should be carefully considered and balanced, with a non-trivial changes
in the implementation of current generator objects. This is a matter
for a separate PEP.</p>
</section>
<section id="why-async-and-await-keywords">
<h3><a class="toc-backref" href="#why-async-and-await-keywords" role="doc-backlink">Why “async” and “await” keywords</a></h3>
<p>async/await is not a new concept in programming languages:</p>
<ul class="simple">
<li>C# has it since long time ago <a class="footnote-reference brackets" href="#id35" id="id17">[5]</a>;</li>
<li>proposal to add async/await in ECMAScript 7 <a class="footnote-reference brackets" href="#id32" id="id18">[2]</a>;
see also Traceur project <a class="footnote-reference brackets" href="#id39" id="id19">[9]</a>;</li>
<li>Facebooks Hack/HHVM <a class="footnote-reference brackets" href="#id36" id="id20">[6]</a>;</li>
<li>Googles Dart language <a class="footnote-reference brackets" href="#id37" id="id21">[7]</a>;</li>
<li>Scala <a class="footnote-reference brackets" href="#id38" id="id22">[8]</a>;</li>
<li>proposal to add async/await to C++ <a class="footnote-reference brackets" href="#id40" id="id23">[10]</a>;</li>
<li>and many other less popular languages.</li>
</ul>
<p>This is a huge benefit, as some users already have experience with
async/await, and because it makes working with many languages in one
project easier (Python with ECMAScript 7 for instance).</p>
</section>
<section id="why-aiter-does-not-return-an-awaitable">
<h3><a class="toc-backref" href="#why-aiter-does-not-return-an-awaitable" role="doc-backlink">Why “__aiter__” does not return an awaitable</a></h3>
<p><a class="pep reference internal" href="../pep-0492/" title="PEP 492 Coroutines with async and await syntax">PEP 492</a> was accepted in CPython 3.5.0 with <code class="docutils literal notranslate"><span class="pre">__aiter__</span></code> defined as
a method, that was expected to return an awaitable resolving to an
asynchronous iterator.</p>
<p>In 3.5.2 (as <a class="pep reference internal" href="../pep-0492/" title="PEP 492 Coroutines with async and await syntax">PEP 492</a> was accepted on a provisional basis) the
<code class="docutils literal notranslate"><span class="pre">__aiter__</span></code> protocol was updated to return asynchronous iterators
directly.</p>
<p>The motivation behind this change is to make it possible to
implement asynchronous generators in Python. See <a class="footnote-reference brackets" href="#id49" id="id24">[19]</a> and <a class="footnote-reference brackets" href="#id50" id="id25">[20]</a> for
more details.</p>
</section>
<section id="importance-of-async-keyword">
<h3><a class="toc-backref" href="#importance-of-async-keyword" role="doc-backlink">Importance of “async” keyword</a></h3>
<p>While it is possible to just implement <code class="docutils literal notranslate"><span class="pre">await</span></code> expression and treat
all functions with at least one <code class="docutils literal notranslate"><span class="pre">await</span></code> as coroutines, this approach
makes APIs design, code refactoring and its long time support harder.</p>
<p>Lets pretend that Python only has <code class="docutils literal notranslate"><span class="pre">await</span></code> keyword:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">useful</span><span class="p">():</span>
<span class="o">...</span>
<span class="k">await</span> <span class="n">log</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
<span class="o">...</span>
<span class="k">def</span> <span class="nf">important</span><span class="p">():</span>
<span class="k">await</span> <span class="n">useful</span><span class="p">()</span>
</pre></div>
</div>
<p>If <code class="docutils literal notranslate"><span class="pre">useful()</span></code> function is refactored and someone removes all
<code class="docutils literal notranslate"><span class="pre">await</span></code> expressions from it, it would become a regular python
function, and all code that depends on it, including <code class="docutils literal notranslate"><span class="pre">important()</span></code>
would be broken. To mitigate this issue a decorator similar to
<code class="docutils literal notranslate"><span class="pre">&#64;asyncio.coroutine</span></code> has to be introduced.</p>
</section>
<section id="why-async-def">
<h3><a class="toc-backref" href="#why-async-def" role="doc-backlink">Why “async def”</a></h3>
<p>For some people bare <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">name():</span> <span class="pre">pass</span></code> syntax might look more
appealing than <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span> <span class="pre">name():</span> <span class="pre">pass</span></code>. It is certainly easier to
type. But on the other hand, it breaks the symmetry between <code class="docutils literal notranslate"><span class="pre">async</span>
<span class="pre">def</span></code>, <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">with</span></code> and <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">for</span></code>, where <code class="docutils literal notranslate"><span class="pre">async</span></code> is a modifier,
stating that the statement is asynchronous. It is also more consistent
with the existing grammar.</p>
</section>
<section id="why-not-await-for-and-await-with">
<h3><a class="toc-backref" href="#why-not-await-for-and-await-with" role="doc-backlink">Why not “await for” and “await with”</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">async</span></code> is an adjective, and hence it is a better choice for a
<em>statement qualifier</em> keyword. <code class="docutils literal notranslate"><span class="pre">await</span> <span class="pre">for/with</span></code> would imply that
something is awaiting for a completion of a <code class="docutils literal notranslate"><span class="pre">for</span></code> or <code class="docutils literal notranslate"><span class="pre">with</span></code>
statement.</p>
</section>
<section id="why-async-def-and-not-def-async">
<h3><a class="toc-backref" href="#why-async-def-and-not-def-async" role="doc-backlink">Why “async def” and not “def async”</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">async</span></code> keyword is a <em>statement qualifier</em>. A good analogy to it are
“static”, “public”, “unsafe” keywords from other languages. “async
for” is an asynchronous “for” statement, “async with” is an
asynchronous “with” statement, “async def” is an asynchronous function.</p>
<p>Having “async” after the main statement keyword might introduce some
confusion, like “for async item in iterator” can be read as “for each
asynchronous item in iterator”.</p>
<p>Having <code class="docutils literal notranslate"><span class="pre">async</span></code> keyword before <code class="docutils literal notranslate"><span class="pre">def</span></code>, <code class="docutils literal notranslate"><span class="pre">with</span></code> and <code class="docutils literal notranslate"><span class="pre">for</span></code> also
makes the language grammar simpler. And “async def” better separates
coroutines from regular functions visually.</p>
</section>
<section id="why-not-a-future-import">
<h3><a class="toc-backref" href="#why-not-a-future-import" role="doc-backlink">Why not a __future__ import</a></h3>
<p><a class="reference internal" href="#transition-plan">Transition Plan</a> section explains how tokenizer is modified to treat
<code class="docutils literal notranslate"><span class="pre">async</span></code> and <code class="docutils literal notranslate"><span class="pre">await</span></code> as keywords <em>only</em> in <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code> blocks.
Hence <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code> fills the role that a module level compiler
declaration like <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">__future__</span> <span class="pre">import</span> <span class="pre">async_await</span></code> would otherwise
fill.</p>
</section>
<section id="why-magic-methods-start-with-a">
<h3><a class="toc-backref" href="#why-magic-methods-start-with-a" role="doc-backlink">Why magic methods start with “a”</a></h3>
<p>New asynchronous magic methods <code class="docutils literal notranslate"><span class="pre">__aiter__</span></code>, <code class="docutils literal notranslate"><span class="pre">__anext__</span></code>,
<code class="docutils literal notranslate"><span class="pre">__aenter__</span></code>, and <code class="docutils literal notranslate"><span class="pre">__aexit__</span></code> all start with the same prefix “a”.
An alternative proposal is to use “async” prefix, so that <code class="docutils literal notranslate"><span class="pre">__anext__</span></code>
becomes <code class="docutils literal notranslate"><span class="pre">__async_next__</span></code>. However, to align new magic methods with
the existing ones, such as <code class="docutils literal notranslate"><span class="pre">__radd__</span></code> and <code class="docutils literal notranslate"><span class="pre">__iadd__</span></code> it was decided
to use a shorter version.</p>
</section>
<section id="why-not-reuse-existing-magic-names">
<h3><a class="toc-backref" href="#why-not-reuse-existing-magic-names" role="doc-backlink">Why not reuse existing magic names</a></h3>
<p>An alternative idea about new asynchronous iterators and context
managers was to reuse existing magic methods, by adding an <code class="docutils literal notranslate"><span class="pre">async</span></code>
keyword to their declarations:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">CM</span><span class="p">:</span>
<span class="k">async</span> <span class="k">def</span> <span class="fm">__enter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="c1"># instead of __aenter__</span>
<span class="o">...</span>
</pre></div>
</div>
<p>This approach has the following downsides:</p>
<ul class="simple">
<li>it would not be possible to create an object that works in both
<code class="docutils literal notranslate"><span class="pre">with</span></code> and <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">with</span></code> statements;</li>
<li>it would break backwards compatibility, as nothing prohibits from
returning a Future-like objects from <code class="docutils literal notranslate"><span class="pre">__enter__</span></code> and/or
<code class="docutils literal notranslate"><span class="pre">__exit__</span></code> in Python &lt;= 3.4;</li>
<li>one of the main points of this proposal is to make native coroutines
as simple and foolproof as possible, hence the clear separation of
the protocols.</li>
</ul>
</section>
<section id="why-not-reuse-existing-for-and-with-statements">
<h3><a class="toc-backref" href="#why-not-reuse-existing-for-and-with-statements" role="doc-backlink">Why not reuse existing “for” and “with” statements</a></h3>
<p>The vision behind existing generator-based coroutines and this proposal
is to make it easy for users to see where the code might be suspended.
Making existing “for” and “with” statements to recognize asynchronous
iterators and context managers will inevitably create implicit suspend
points, making it harder to reason about the code.</p>
</section>
<section id="comprehensions">
<h3><a class="toc-backref" href="#comprehensions" role="doc-backlink">Comprehensions</a></h3>
<p>Syntax for asynchronous comprehensions could be provided, but this
construct is outside of the scope of this PEP.</p>
</section>
<section id="async-lambda-functions">
<h3><a class="toc-backref" href="#async-lambda-functions" role="doc-backlink">Async lambda functions</a></h3>
<p>Syntax for asynchronous lambda functions could be provided, but this
construct is outside of the scope of this PEP.</p>
</section>
</section>
<section id="performance">
<h2><a class="toc-backref" href="#performance" role="doc-backlink">Performance</a></h2>
<section id="overall-impact">
<h3><a class="toc-backref" href="#overall-impact" role="doc-backlink">Overall Impact</a></h3>
<p>This proposal introduces no observable performance impact. Here is an
output of pythons official set of benchmarks <a class="footnote-reference brackets" href="#id34" id="id26">[4]</a>:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>python perf.py -r -b default ../cpython/python.exe ../cpython-aw/python.exe
[skipped]
Report on Darwin ysmac 14.3.0 Darwin Kernel Version 14.3.0:
Mon Mar 23 11:59:05 PDT 2015; root:xnu-2782.20.48~5/RELEASE_X86_64
x86_64 i386
Total CPU cores: 8
### etree_iterparse ###
Min: 0.365359 -&gt; 0.349168: 1.05x faster
Avg: 0.396924 -&gt; 0.379735: 1.05x faster
Significant (t=9.71)
Stddev: 0.01225 -&gt; 0.01277: 1.0423x larger
The following not significant results are hidden, use -v to show them:
django_v2, 2to3, etree_generate, etree_parse, etree_process, fastpickle,
fastunpickle, json_dump_v2, json_load, nbody, regex_v8, tornado_http.
</pre></div>
</div>
</section>
<section id="tokenizer-modifications">
<h3><a class="toc-backref" href="#tokenizer-modifications" role="doc-backlink">Tokenizer modifications</a></h3>
<p>There is no observable slowdown of parsing python files with the
modified tokenizer: parsing of one 12Mb file
(<code class="docutils literal notranslate"><span class="pre">Lib/test/test_binop.py</span></code> repeated 1000 times) takes the same amount
of time.</p>
</section>
<section id="async-await">
<h3><a class="toc-backref" href="#async-await" role="doc-backlink">async/await</a></h3>
<p>The following micro-benchmark was used to determine performance
difference between “async” functions and generators:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="k">def</span> <span class="nf">binary</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">if</span> <span class="n">n</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">1</span>
<span class="n">l</span> <span class="o">=</span> <span class="k">yield from</span> <span class="n">binary</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">r</span> <span class="o">=</span> <span class="k">yield from</span> <span class="n">binary</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">return</span> <span class="n">l</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">+</span> <span class="n">r</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">abinary</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">if</span> <span class="n">n</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">1</span>
<span class="n">l</span> <span class="o">=</span> <span class="k">await</span> <span class="n">abinary</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">r</span> <span class="o">=</span> <span class="k">await</span> <span class="n">abinary</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">return</span> <span class="n">l</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">+</span> <span class="n">r</span>
<span class="k">def</span> <span class="nf">timeit</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">depth</span><span class="p">,</span> <span class="n">repeat</span><span class="p">):</span>
<span class="n">t0</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="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">repeat</span><span class="p">):</span>
<span class="n">o</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="n">depth</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">o</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">StopIteration</span><span class="p">:</span>
<span class="k">pass</span>
<span class="n">t1</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="nb">print</span><span class="p">(</span><span class="s1">&#39;</span><span class="si">{}</span><span class="s1">(</span><span class="si">{}</span><span class="s1">) * </span><span class="si">{}</span><span class="s1">: total </span><span class="si">{:.3f}</span><span class="s1">s&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
<span class="n">func</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="n">depth</span><span class="p">,</span> <span class="n">repeat</span><span class="p">,</span> <span class="n">t1</span><span class="o">-</span><span class="n">t0</span><span class="p">))</span>
</pre></div>
</div>
<p>The result is that there is no observable performance difference:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">binary</span><span class="p">(</span><span class="mi">19</span><span class="p">)</span> <span class="o">*</span> <span class="mi">30</span><span class="p">:</span> <span class="n">total</span> <span class="mf">53.321</span><span class="n">s</span>
<span class="n">abinary</span><span class="p">(</span><span class="mi">19</span><span class="p">)</span> <span class="o">*</span> <span class="mi">30</span><span class="p">:</span> <span class="n">total</span> <span class="mf">55.073</span><span class="n">s</span>
<span class="n">binary</span><span class="p">(</span><span class="mi">19</span><span class="p">)</span> <span class="o">*</span> <span class="mi">30</span><span class="p">:</span> <span class="n">total</span> <span class="mf">53.361</span><span class="n">s</span>
<span class="n">abinary</span><span class="p">(</span><span class="mi">19</span><span class="p">)</span> <span class="o">*</span> <span class="mi">30</span><span class="p">:</span> <span class="n">total</span> <span class="mf">51.360</span><span class="n">s</span>
<span class="n">binary</span><span class="p">(</span><span class="mi">19</span><span class="p">)</span> <span class="o">*</span> <span class="mi">30</span><span class="p">:</span> <span class="n">total</span> <span class="mf">49.438</span><span class="n">s</span>
<span class="n">abinary</span><span class="p">(</span><span class="mi">19</span><span class="p">)</span> <span class="o">*</span> <span class="mi">30</span><span class="p">:</span> <span class="n">total</span> <span class="mf">51.047</span><span class="n">s</span>
</pre></div>
</div>
<p>Note that depth of 19 means 1,048,575 calls.</p>
</section>
</section>
<section id="reference-implementation">
<h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2>
<p>The reference implementation can be found here: <a class="footnote-reference brackets" href="#id33" id="id27">[3]</a>.</p>
<section id="list-of-high-level-changes-and-new-protocols">
<h3><a class="toc-backref" href="#list-of-high-level-changes-and-new-protocols" role="doc-backlink">List of high-level changes and new protocols</a></h3>
<ol class="arabic simple">
<li>New syntax for defining coroutines: <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code> and new <code class="docutils literal notranslate"><span class="pre">await</span></code>
keyword.</li>
<li>New <code class="docutils literal notranslate"><span class="pre">__await__</span></code> method for Future-like objects, and new
<code class="docutils literal notranslate"><span class="pre">tp_as_async.am_await</span></code> slot in <code class="docutils literal notranslate"><span class="pre">PyTypeObject</span></code>.</li>
<li>New syntax for asynchronous context managers: <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">with</span></code>. And
associated protocol with <code class="docutils literal notranslate"><span class="pre">__aenter__</span></code> and <code class="docutils literal notranslate"><span class="pre">__aexit__</span></code> methods.</li>
<li>New syntax for asynchronous iteration: <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">for</span></code>. And
associated protocol with <code class="docutils literal notranslate"><span class="pre">__aiter__</span></code>, <code class="docutils literal notranslate"><span class="pre">__aexit__</span></code> and new built-in
exception <code class="docutils literal notranslate"><span class="pre">StopAsyncIteration</span></code>. New <code class="docutils literal notranslate"><span class="pre">tp_as_async.am_aiter</span></code>
and <code class="docutils literal notranslate"><span class="pre">tp_as_async.am_anext</span></code> slots in <code class="docutils literal notranslate"><span class="pre">PyTypeObject</span></code>.</li>
<li>New AST nodes: <code class="docutils literal notranslate"><span class="pre">AsyncFunctionDef</span></code>, <code class="docutils literal notranslate"><span class="pre">AsyncFor</span></code>, <code class="docutils literal notranslate"><span class="pre">AsyncWith</span></code>,
<code class="docutils literal notranslate"><span class="pre">Await</span></code>.</li>
<li>New functions: <code class="docutils literal notranslate"><span class="pre">sys.set_coroutine_wrapper(callback)</span></code>,
<code class="docutils literal notranslate"><span class="pre">sys.get_coroutine_wrapper()</span></code>, <code class="docutils literal notranslate"><span class="pre">types.coroutine(gen)</span></code>,
<code class="docutils literal notranslate"><span class="pre">inspect.iscoroutinefunction(func)</span></code>, <code class="docutils literal notranslate"><span class="pre">inspect.iscoroutine(obj)</span></code>,
<code class="docutils literal notranslate"><span class="pre">inspect.isawaitable(obj)</span></code>, <code class="docutils literal notranslate"><span class="pre">inspect.getcoroutinestate(coro)</span></code>,
and <code class="docutils literal notranslate"><span class="pre">inspect.getcoroutinelocals(coro)</span></code>.</li>
<li>New <code class="docutils literal notranslate"><span class="pre">CO_COROUTINE</span></code> and <code class="docutils literal notranslate"><span class="pre">CO_ITERABLE_COROUTINE</span></code> bit flags for code
objects.</li>
<li>New ABCs: <code class="docutils literal notranslate"><span class="pre">collections.abc.Awaitable</span></code>,
<code class="docutils literal notranslate"><span class="pre">collections.abc.Coroutine</span></code>, <code class="docutils literal notranslate"><span class="pre">collections.abc.AsyncIterable</span></code>, and
<code class="docutils literal notranslate"><span class="pre">collections.abc.AsyncIterator</span></code>.</li>
<li>C API changes: new <code class="docutils literal notranslate"><span class="pre">PyCoro_Type</span></code> (exposed to Python as
<code class="docutils literal notranslate"><span class="pre">types.CoroutineType</span></code>) and <code class="docutils literal notranslate"><span class="pre">PyCoroObject</span></code>.
<code class="docutils literal notranslate"><span class="pre">PyCoro_CheckExact(*o)</span></code> to test if <code class="docutils literal notranslate"><span class="pre">o</span></code> is a <em>native coroutine</em>.</li>
</ol>
<p>While the list of changes and new things is not short, it is important
to understand, that most users will not use these features directly.
It is intended to be used in frameworks and libraries to provide users
with convenient to use and unambiguous APIs with <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code>,
<code class="docutils literal notranslate"><span class="pre">await</span></code>, <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">for</span></code> and <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">with</span></code> syntax.</p>
</section>
<section id="working-example">
<h3><a class="toc-backref" href="#working-example" role="doc-backlink">Working example</a></h3>
<p>All concepts proposed in this PEP are implemented <a class="footnote-reference brackets" href="#id33" id="id28">[3]</a> and can be
tested.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">asyncio</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">echo_server</span><span class="p">():</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;Serving on localhost:8000&#39;</span><span class="p">)</span>
<span class="k">await</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">start_server</span><span class="p">(</span><span class="n">handle_connection</span><span class="p">,</span>
<span class="s1">&#39;localhost&#39;</span><span class="p">,</span> <span class="mi">8000</span><span class="p">)</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">handle_connection</span><span class="p">(</span><span class="n">reader</span><span class="p">,</span> <span class="n">writer</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;New connection...&#39;</span><span class="p">)</span>
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
<span class="n">data</span> <span class="o">=</span> <span class="k">await</span> <span class="n">reader</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="mi">8192</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">data</span><span class="p">:</span>
<span class="k">break</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;Sending </span><span class="si">{:.10}</span><span class="s1">... back&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">repr</span><span class="p">(</span><span class="n">data</span><span class="p">)))</span>
<span class="n">writer</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="n">loop</span> <span class="o">=</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">get_event_loop</span><span class="p">()</span>
<span class="n">loop</span><span class="o">.</span><span class="n">run_until_complete</span><span class="p">(</span><span class="n">echo_server</span><span class="p">())</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">loop</span><span class="o">.</span><span class="n">run_forever</span><span class="p">()</span>
<span class="k">finally</span><span class="p">:</span>
<span class="n">loop</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>
</div>
</section>
</section>
<section id="acceptance">
<h2><a class="toc-backref" href="#acceptance" role="doc-backlink">Acceptance</a></h2>
<p><a class="pep reference internal" href="../pep-0492/" title="PEP 492 Coroutines with async and await syntax">PEP 492</a> was accepted by Guido, Tuesday, May 5, 2015 <a class="footnote-reference brackets" href="#id44" id="id29">[14]</a>.</p>
</section>
<section id="implementation">
<h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2>
<p>The implementation is tracked in issue 24017 <a class="footnote-reference brackets" href="#id45" id="id30">[15]</a>. It was
committed on May 11, 2015.</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="id31" role="doc-footnote">
<dt class="label" id="id31">[<a href="#id13">1</a>]</dt>
<dd><a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.coroutine">https://docs.python.org/3/library/asyncio-task.html#asyncio.coroutine</a></aside>
<aside class="footnote brackets" id="id32" role="doc-footnote">
<dt class="label" id="id32">[2]<em> (<a href='#id1'>1</a>, <a href='#id18'>2</a>) </em></dt>
<dd><a class="reference external" href="http://wiki.ecmascript.org/doku.php?id=strawman:async_functions">http://wiki.ecmascript.org/doku.php?id=strawman:async_functions</a></aside>
<aside class="footnote brackets" id="id33" role="doc-footnote">
<dt class="label" id="id33">[3]<em> (<a href='#id27'>1</a>, <a href='#id28'>2</a>) </em></dt>
<dd><a class="reference external" href="https://github.com/1st1/cpython/tree/await">https://github.com/1st1/cpython/tree/await</a></aside>
<aside class="footnote brackets" id="id34" role="doc-footnote">
<dt class="label" id="id34">[<a href="#id26">4</a>]</dt>
<dd><a class="reference external" href="https://hg.python.org/benchmarks">https://hg.python.org/benchmarks</a></aside>
<aside class="footnote brackets" id="id35" role="doc-footnote">
<dt class="label" id="id35">[5]<em> (<a href='#id2'>1</a>, <a href='#id17'>2</a>) </em></dt>
<dd><a class="reference external" href="https://msdn.microsoft.com/en-us/library/hh191443.aspx">https://msdn.microsoft.com/en-us/library/hh191443.aspx</a></aside>
<aside class="footnote brackets" id="id36" role="doc-footnote">
<dt class="label" id="id36">[6]<em> (<a href='#id3'>1</a>, <a href='#id20'>2</a>) </em></dt>
<dd><a class="reference external" href="http://docs.hhvm.com/manual/en/hack.async.php">http://docs.hhvm.com/manual/en/hack.async.php</a></aside>
<aside class="footnote brackets" id="id37" role="doc-footnote">
<dt class="label" id="id37">[7]<em> (<a href='#id4'>1</a>, <a href='#id21'>2</a>) </em></dt>
<dd><a class="reference external" href="https://www.dartlang.org/articles/await-async/">https://www.dartlang.org/articles/await-async/</a></aside>
<aside class="footnote brackets" id="id38" role="doc-footnote">
<dt class="label" id="id38">[8]<em> (<a href='#id5'>1</a>, <a href='#id22'>2</a>) </em></dt>
<dd><a class="reference external" href="http://docs.scala-lang.org/sips/pending/async.html">http://docs.scala-lang.org/sips/pending/async.html</a></aside>
<aside class="footnote brackets" id="id39" role="doc-footnote">
<dt class="label" id="id39">[<a href="#id19">9</a>]</dt>
<dd><a class="reference external" href="https://github.com/google/traceur-compiler/wiki/LanguageFeatures#async-functions-experimental">https://github.com/google/traceur-compiler/wiki/LanguageFeatures#async-functions-experimental</a></aside>
<aside class="footnote brackets" id="id40" role="doc-footnote">
<dt class="label" id="id40">[10]<em> (<a href='#id6'>1</a>, <a href='#id23'>2</a>) </em></dt>
<dd><a class="reference external" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3722.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3722.pdf</a> (PDF)</aside>
<aside class="footnote brackets" id="id41" role="doc-footnote">
<dt class="label" id="id41">[<a href="#id14">11</a>]</dt>
<dd><a class="reference external" href="https://docs.python.org/3/reference/expressions.html#generator-iterator-methods">https://docs.python.org/3/reference/expressions.html#generator-iterator-methods</a></aside>
<aside class="footnote brackets" id="id42" role="doc-footnote">
<dt class="label" id="id42">[<a href="#id11">12</a>]</dt>
<dd><a class="reference external" href="https://docs.python.org/3/reference/expressions.html#primaries">https://docs.python.org/3/reference/expressions.html#primaries</a></aside>
<aside class="footnote brackets" id="id43" role="doc-footnote">
<dt class="label" id="id43">[<a href="#id15">13</a>]</dt>
<dd><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2015-May/139851.html">https://mail.python.org/pipermail/python-dev/2015-May/139851.html</a></aside>
<aside class="footnote brackets" id="id44" role="doc-footnote">
<dt class="label" id="id44">[<a href="#id29">14</a>]</dt>
<dd><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2015-May/139844.html">https://mail.python.org/pipermail/python-dev/2015-May/139844.html</a></aside>
<aside class="footnote brackets" id="id45" role="doc-footnote">
<dt class="label" id="id45">[<a href="#id30">15</a>]</dt>
<dd><a class="reference external" href="http://bugs.python.org/issue24017">http://bugs.python.org/issue24017</a></aside>
<aside class="footnote brackets" id="id46" role="doc-footnote">
<dt class="label" id="id46">[<a href="#id16">16</a>]</dt>
<dd><a class="reference external" href="https://github.com/python/asyncio/issues/233">https://github.com/python/asyncio/issues/233</a></aside>
<aside class="footnote brackets" id="id47" role="doc-footnote">
<dt class="label" id="id47">[<a href="#id7">17</a>]</dt>
<dd><a class="reference external" href="https://hg.python.org/cpython/rev/7a0a1a4ac639">https://hg.python.org/cpython/rev/7a0a1a4ac639</a></aside>
<aside class="footnote brackets" id="id48" role="doc-footnote">
<dt class="label" id="id48">[<a href="#id8">18</a>]</dt>
<dd><a class="reference external" href="http://bugs.python.org/issue24400">http://bugs.python.org/issue24400</a></aside>
<aside class="footnote brackets" id="id49" role="doc-footnote">
<dt class="label" id="id49">[19]<em> (<a href='#id9'>1</a>, <a href='#id24'>2</a>) </em></dt>
<dd><a class="reference external" href="http://bugs.python.org/issue27243">http://bugs.python.org/issue27243</a></aside>
<aside class="footnote brackets" id="id50" role="doc-footnote">
<dt class="label" id="id50">[20]<em> (<a href='#id10'>1</a>, <a href='#id25'>2</a>) </em></dt>
<dd><a class="reference external" href="https://docs.python.org/3/reference/datamodel.html#async-iterators">https://docs.python.org/3/reference/datamodel.html#async-iterators</a></aside>
</aside>
</section>
<section id="acknowledgments">
<h2><a class="toc-backref" href="#acknowledgments" role="doc-backlink">Acknowledgments</a></h2>
<p>I thank Guido van Rossum, Victor Stinner, Elvis Pranskevichus, Andrew
Svetlov, Łukasz Langa, Greg Ewing, Stephen J. Turnbull, Jim J. Jewett,
Brett Cannon, Alyssa Coghlan, Steven DAprano, Paul Moore, Nathaniel
Smith, Ethan Furman, Stefan Behnel, Paul Sokolovsky, Victor Petrovykh,
and many others for their feedback, ideas, edits, criticism, code
reviews, and discussions around this PEP.</p>
</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-0492.rst">https://github.com/python/peps/blob/main/peps/pep-0492.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0492.rst">2023-10-11 12:05: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="#api-design-and-implementation-revisions">API Design and Implementation Revisions</a></li>
<li><a class="reference internal" href="#rationale-and-goals">Rationale and Goals</a></li>
<li><a class="reference internal" href="#specification">Specification</a><ul>
<li><a class="reference internal" href="#new-coroutine-declaration-syntax">New Coroutine Declaration Syntax</a></li>
<li><a class="reference internal" href="#types-coroutine">types.coroutine()</a></li>
<li><a class="reference internal" href="#await-expression">Await Expression</a><ul>
<li><a class="reference internal" href="#updated-operator-precedence-table">Updated operator precedence table</a></li>
<li><a class="reference internal" href="#examples-of-await-expressions">Examples of “await” expressions</a></li>
</ul>
</li>
<li><a class="reference internal" href="#asynchronous-context-managers-and-async-with">Asynchronous Context Managers and “async with”</a><ul>
<li><a class="reference internal" href="#new-syntax">New Syntax</a></li>
<li><a class="reference internal" href="#example">Example</a></li>
</ul>
</li>
<li><a class="reference internal" href="#asynchronous-iterators-and-async-for">Asynchronous Iterators and “async for”</a><ul>
<li><a class="reference internal" href="#id12">New Syntax</a></li>
<li><a class="reference internal" href="#example-1">Example 1</a></li>
<li><a class="reference internal" href="#example-2">Example 2</a></li>
<li><a class="reference internal" href="#why-stopasynciteration">Why StopAsyncIteration?</a></li>
</ul>
</li>
<li><a class="reference internal" href="#coroutine-objects">Coroutine objects</a><ul>
<li><a class="reference internal" href="#differences-from-generators">Differences from generators</a></li>
<li><a class="reference internal" href="#coroutine-object-methods">Coroutine object methods</a></li>
</ul>
</li>
<li><a class="reference internal" href="#debugging-features">Debugging Features</a></li>
<li><a class="reference internal" href="#new-standard-library-functions">New Standard Library Functions</a></li>
<li><a class="reference internal" href="#new-abstract-base-classes">New Abstract Base Classes</a></li>
</ul>
</li>
<li><a class="reference internal" href="#glossary">Glossary</a></li>
<li><a class="reference internal" href="#transition-plan">Transition Plan</a><ul>
<li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a><ul>
<li><a class="reference internal" href="#asyncio">asyncio</a></li>
<li><a class="reference internal" href="#asyncio-migration-strategy">asyncio migration strategy</a></li>
<li><a class="reference internal" href="#async-await-in-cpython-code-base">async/await in CPython code base</a></li>
</ul>
</li>
<li><a class="reference internal" href="#grammar-updates">Grammar Updates</a></li>
<li><a class="reference internal" href="#deprecation-plans">Deprecation Plans</a></li>
</ul>
</li>
<li><a class="reference internal" href="#design-considerations">Design Considerations</a><ul>
<li><a class="reference internal" href="#pep-3152">PEP 3152</a></li>
<li><a class="reference internal" href="#coroutine-generators">Coroutine-generators</a></li>
<li><a class="reference internal" href="#why-async-and-await-keywords">Why “async” and “await” keywords</a></li>
<li><a class="reference internal" href="#why-aiter-does-not-return-an-awaitable">Why “__aiter__” does not return an awaitable</a></li>
<li><a class="reference internal" href="#importance-of-async-keyword">Importance of “async” keyword</a></li>
<li><a class="reference internal" href="#why-async-def">Why “async def”</a></li>
<li><a class="reference internal" href="#why-not-await-for-and-await-with">Why not “await for” and “await with”</a></li>
<li><a class="reference internal" href="#why-async-def-and-not-def-async">Why “async def” and not “def async”</a></li>
<li><a class="reference internal" href="#why-not-a-future-import">Why not a __future__ import</a></li>
<li><a class="reference internal" href="#why-magic-methods-start-with-a">Why magic methods start with “a”</a></li>
<li><a class="reference internal" href="#why-not-reuse-existing-magic-names">Why not reuse existing magic names</a></li>
<li><a class="reference internal" href="#why-not-reuse-existing-for-and-with-statements">Why not reuse existing “for” and “with” statements</a></li>
<li><a class="reference internal" href="#comprehensions">Comprehensions</a></li>
<li><a class="reference internal" href="#async-lambda-functions">Async lambda functions</a></li>
</ul>
</li>
<li><a class="reference internal" href="#performance">Performance</a><ul>
<li><a class="reference internal" href="#overall-impact">Overall Impact</a></li>
<li><a class="reference internal" href="#tokenizer-modifications">Tokenizer modifications</a></li>
<li><a class="reference internal" href="#async-await">async/await</a></li>
</ul>
</li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a><ul>
<li><a class="reference internal" href="#list-of-high-level-changes-and-new-protocols">List of high-level changes and new protocols</a></li>
<li><a class="reference internal" href="#working-example">Working example</a></li>
</ul>
</li>
<li><a class="reference internal" href="#acceptance">Acceptance</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#acknowledgments">Acknowledgments</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-0492.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>