Files
hustoj/web/python-docs/library/asyncio-task.html
2025-03-09 17:10:56 +08:00

1060 lines
94 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh_CN">
<head>
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>协程与任务 &#8212; Python 3.8.20 文档</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script src="../_static/translations.js"></script>
<script src="../_static/sidebar.js"></script>
<link rel="search" type="application/opensearchdescription+xml"
title="在 Python 3.8.20 文档 中搜索"
href="../_static/opensearch.xml"/>
<link rel="author" title="关于这些文档" href="../about.html" />
<link rel="index" title="索引" href="../genindex.html" />
<link rel="search" title="搜索" href="../search.html" />
<link rel="copyright" title="版权所有" href="../copyright.html" />
<link rel="next" title="流" href="asyncio-stream.html" />
<link rel="prev" title="asyncio --- 异步 I/O" href="asyncio.html" />
<link rel="canonical" href="https://docs.python.org/3/library/asyncio-task.html" />
<style>
@media only screen {
table.full-width-table {
width: 100%;
}
}
</style>
<link rel="shortcut icon" type="image/png" href="../_static/py.svg" />
<script type="text/javascript" src="../_static/copybutton.js"></script>
<script type="text/javascript" src="../_static/menu.js"></script>
</head>
<body>
<div class="mobile-nav">
<input type="checkbox" id="menuToggler" class="toggler__input" aria-controls="navigation"
aria-pressed="false" aria-expanded="false" role="button" aria-label="Menu" />
<label for="menuToggler" class="toggler__label">
<span></span>
</label>
<nav class="nav-content" role="navigation">
<a href="https://www.python.org/" class="nav-logo">
<img src="../_static/py.svg" alt="Logo"/>
</a>
<div class="version_switcher_placeholder"></div>
<form role="search" class="search" action="../search.html" method="get">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
<path fill-rule="nonzero"
d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" fill="#444"></path>
</svg>
<input type="text" name="q" aria-label="快速搜索"/>
<input type="submit" value="转向"/>
</form>
</nav>
<div class="menu-wrapper">
<nav class="menu" role="navigation" aria-label="main navigation">
<div class="language_switcher_placeholder"></div>
<h3><a href="../contents.html">目录</a></h3>
<ul>
<li><a class="reference internal" href="#">协程与任务</a><ul>
<li><a class="reference internal" href="#coroutines">协程</a></li>
<li><a class="reference internal" href="#awaitables">可等待对象</a></li>
<li><a class="reference internal" href="#running-an-asyncio-program">运行 asyncio 程序</a></li>
<li><a class="reference internal" href="#creating-tasks">创建任务</a></li>
<li><a class="reference internal" href="#sleeping">休眠</a></li>
<li><a class="reference internal" href="#running-tasks-concurrently">并发运行任务</a></li>
<li><a class="reference internal" href="#shielding-from-cancellation">屏蔽取消操作</a></li>
<li><a class="reference internal" href="#timeouts">超时</a></li>
<li><a class="reference internal" href="#waiting-primitives">简单等待</a></li>
<li><a class="reference internal" href="#scheduling-from-other-threads">跨线程调度</a></li>
<li><a class="reference internal" href="#introspection">内省</a></li>
<li><a class="reference internal" href="#task-object">Task 对象</a></li>
<li><a class="reference internal" href="#generator-based-coroutines">基于生成器的协程</a></li>
</ul>
</li>
</ul>
<h4>上一个主题</h4>
<p class="topless"><a href="asyncio.html"
title="上一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">asyncio</span></code> --- 异步 I/O</a></p>
<h4>下一个主题</h4>
<p class="topless"><a href="asyncio-stream.html"
title="下一章"></a></p>
<div role="note" aria-label="source link">
<h3>本页</h3>
<ul class="this-page-menu">
<li><a href="../bugs.html">报告 Bug</a></li>
<li>
<a href="https://github.com/python/cpython/blob/3.8/Doc/library/asyncio-task.rst"
rel="nofollow">显示源代码
</a>
</li>
</ul>
</div>
</nav>
</div>
</div>
<div id="outdated-warning" style="padding: .5em; text-align: center; background-color: #FFBABA; color: #6A0E0E;">
这个文档所针对的是一个已不再受支持的 Python 旧版本。
你应当升级版本,并阅读
<a href="/3/library/asyncio-task.html"> Python 当前稳定版本的文档</a>.
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>导航</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="总目录"
accesskey="I">索引</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python 模块索引"
>模块</a> |</li>
<li class="right" >
<a href="asyncio-stream.html" title="流"
accesskey="N">下一页</a> |</li>
<li class="right" >
<a href="asyncio.html" title="asyncio --- 异步 I/O"
accesskey="P">上一页</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.8.20 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python 标准库</a> &#187;</li>
<li class="nav-item nav-item-2"><a href="ipc.html" >网络和进程间通信</a> &#187;</li>
<li class="nav-item nav-item-3"><a href="asyncio.html" accesskey="U"><code class="xref py py-mod docutils literal notranslate"><span class="pre">asyncio</span></code> --- 异步 I/O</a> &#187;</li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="快速搜索" aria-label="快速搜索" type="text" name="q" />
<input type="submit" value="转向" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
|
</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="coroutines-and-tasks">
<h1>协程与任务<a class="headerlink" href="#coroutines-and-tasks" title="永久链接至标题"></a></h1>
<p>本节将简述用于协程与任务的高层级 API。</p>
<div class="contents local topic" id="id1">
<ul class="simple">
<li><p><a class="reference internal" href="#coroutines" id="id2">协程</a></p></li>
<li><p><a class="reference internal" href="#awaitables" id="id3">可等待对象</a></p></li>
<li><p><a class="reference internal" href="#running-an-asyncio-program" id="id4">运行 asyncio 程序</a></p></li>
<li><p><a class="reference internal" href="#creating-tasks" id="id5">创建任务</a></p></li>
<li><p><a class="reference internal" href="#sleeping" id="id6">休眠</a></p></li>
<li><p><a class="reference internal" href="#running-tasks-concurrently" id="id7">并发运行任务</a></p></li>
<li><p><a class="reference internal" href="#shielding-from-cancellation" id="id8">屏蔽取消操作</a></p></li>
<li><p><a class="reference internal" href="#timeouts" id="id9">超时</a></p></li>
<li><p><a class="reference internal" href="#waiting-primitives" id="id10">简单等待</a></p></li>
<li><p><a class="reference internal" href="#scheduling-from-other-threads" id="id11">跨线程调度</a></p></li>
<li><p><a class="reference internal" href="#introspection" id="id12">内省</a></p></li>
<li><p><a class="reference internal" href="#task-object" id="id13">Task 对象</a></p></li>
<li><p><a class="reference internal" href="#generator-based-coroutines" id="id14">基于生成器的协程</a></p></li>
</ul>
</div>
<section id="coroutines">
<span id="coroutine"></span><h2><a class="toc-backref" href="#id2">协程</a><a class="headerlink" href="#coroutines" title="永久链接至标题"></a></h2>
<p><a class="reference internal" href="../glossary.html#term-coroutine"><span class="xref std std-term">协程</span></a> 通过 async/await 语法进行声明,是编写 asyncio 应用的推荐方式。 例如,以下代码段(需要 Python 3.7+)会打印 &quot;hello&quot;,等待 1 秒,再打印 &quot;world&quot;:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">asyncio</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;hello&#39;</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">await</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="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;world&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">())</span>
<span class="go">hello</span>
<span class="go">world</span>
</pre></div>
</div>
<p>注意:简单地调用一个协程并不会使其被调度执行</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">main</span><span class="p">()</span>
<span class="go">&lt;coroutine object main at 0x1053bb7c8&gt;</span>
</pre></div>
</div>
<p>要真正运行一个协程asyncio 提供了三种主要机制:</p>
<ul>
<li><p><a class="reference internal" href="#asyncio.run" title="asyncio.run"><code class="xref py py-func docutils literal notranslate"><span class="pre">asyncio.run()</span></code></a> 函数用来运行最高层级的入口点 &quot;main()&quot; 函数 (参见上面的示例。)</p></li>
<li><p>对协程执行 await。以下代码段会在等待 1 秒后打印 &quot;hello&quot;,然后 <em>再次</em> 等待 2 秒后打印 &quot;world&quot;:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">asyncio</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">say_after</span><span class="p">(</span><span class="n">delay</span><span class="p">,</span> <span class="n">what</span><span class="p">):</span>
<span class="k">await</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="n">delay</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">what</span><span class="p">)</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;started at </span><span class="si">{</span><span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">&#39;</span><span class="si">%X</span><span class="s1">&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">await</span> <span class="n">say_after</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s1">&#39;hello&#39;</span><span class="p">)</span>
<span class="k">await</span> <span class="n">say_after</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="s1">&#39;world&#39;</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;finished at </span><span class="si">{</span><span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">&#39;</span><span class="si">%X</span><span class="s1">&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">())</span>
</pre></div>
</div>
<p>预期的输出:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">started</span> <span class="n">at</span> <span class="mi">17</span><span class="p">:</span><span class="mi">13</span><span class="p">:</span><span class="mi">52</span>
<span class="n">hello</span>
<span class="n">world</span>
<span class="n">finished</span> <span class="n">at</span> <span class="mi">17</span><span class="p">:</span><span class="mi">13</span><span class="p">:</span><span class="mi">55</span>
</pre></div>
</div>
</li>
<li><p><a class="reference internal" href="#asyncio.create_task" title="asyncio.create_task"><code class="xref py py-func docutils literal notranslate"><span class="pre">asyncio.create_task()</span></code></a> 函数用来并发运行作为 asyncio <a class="reference internal" href="#asyncio.Task" title="asyncio.Task"><code class="xref py py-class docutils literal notranslate"><span class="pre">任务</span></code></a> 的多个协程。</p>
<p>让我们修改以上示例,<em>并发</em> 运行两个 <code class="docutils literal notranslate"><span class="pre">say_after</span></code> 协程:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">task1</span> <span class="o">=</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">create_task</span><span class="p">(</span>
<span class="n">say_after</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s1">&#39;hello&#39;</span><span class="p">))</span>
<span class="n">task2</span> <span class="o">=</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">create_task</span><span class="p">(</span>
<span class="n">say_after</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="s1">&#39;world&#39;</span><span class="p">))</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;started at </span><span class="si">{</span><span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">&#39;</span><span class="si">%X</span><span class="s1">&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="c1"># Wait until both tasks are completed (should take</span>
<span class="c1"># around 2 seconds.)</span>
<span class="k">await</span> <span class="n">task1</span>
<span class="k">await</span> <span class="n">task2</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;finished at </span><span class="si">{</span><span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">&#39;</span><span class="si">%X</span><span class="s1">&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>注意,预期的输出显示代码段的运行时间比之前快了 1 秒:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">started</span> <span class="n">at</span> <span class="mi">17</span><span class="p">:</span><span class="mi">14</span><span class="p">:</span><span class="mi">32</span>
<span class="n">hello</span>
<span class="n">world</span>
<span class="n">finished</span> <span class="n">at</span> <span class="mi">17</span><span class="p">:</span><span class="mi">14</span><span class="p">:</span><span class="mi">34</span>
</pre></div>
</div>
</li>
</ul>
</section>
<section id="awaitables">
<span id="asyncio-awaitables"></span><h2><a class="toc-backref" href="#id3">可等待对象</a><a class="headerlink" href="#awaitables" title="永久链接至标题"></a></h2>
<p>如果一个对象可以在 <a class="reference internal" href="../reference/expressions.html#await"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">await</span></code></a> 语句中使用,那么它就是 <strong>可等待</strong> 对象。许多 asyncio API 都被设计为接受可等待对象。</p>
<p><em>可等待</em> 对象有三种主要类型: <strong>协程</strong>, <strong>任务</strong><strong>Future</strong>.</p>
<p class="rubric">协程</p>
<p>Python 协程属于 <em>可等待</em> 对象,因此可以在其他协程中被等待:</p>
<div class="highlight-python3 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">nested</span><span class="p">():</span>
<span class="k">return</span> <span class="mi">42</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="c1"># Nothing happens if we just call &quot;nested()&quot;.</span>
<span class="c1"># A coroutine object is created but not awaited,</span>
<span class="c1"># so it *won&#39;t run at all*.</span>
<span class="n">nested</span><span class="p">()</span>
<span class="c1"># Let&#39;s do it differently now and await it:</span>
<span class="nb">print</span><span class="p">(</span><span class="k">await</span> <span class="n">nested</span><span class="p">())</span> <span class="c1"># will print &quot;42&quot;.</span>
<span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">())</span>
</pre></div>
</div>
<div class="admonition important">
<p class="admonition-title">重要</p>
<p>在本文档中 &quot;协程&quot; 可用来表示两个紧密关联的概念:</p>
<ul class="simple">
<li><p><em>协程函数</em>: 定义形式为 <a class="reference internal" href="../reference/compound_stmts.html#async-def"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code></a> 的函数;</p></li>
<li><p><em>协程对象</em>: 调用 <em>协程函数</em> 所返回的对象。</p></li>
</ul>
</div>
<p>asyncio 也支持旧式的 <a class="reference internal" href="#asyncio-generator-based-coro"><span class="std std-ref">基于生成器的</span></a> 协程。</p>
<p class="rubric">任务</p>
<p><em>任务</em> 被用来“并行的”调度协程</p>
<p>当一个协程通过 <a class="reference internal" href="#asyncio.create_task" title="asyncio.create_task"><code class="xref py py-func docutils literal notranslate"><span class="pre">asyncio.create_task()</span></code></a> 等函数被封装为一个 <em>任务</em>,该协程会被自动调度执行:</p>
<div class="highlight-python3 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">nested</span><span class="p">():</span>
<span class="k">return</span> <span class="mi">42</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="c1"># Schedule nested() to run soon concurrently</span>
<span class="c1"># with &quot;main()&quot;.</span>
<span class="n">task</span> <span class="o">=</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">create_task</span><span class="p">(</span><span class="n">nested</span><span class="p">())</span>
<span class="c1"># &quot;task&quot; can now be used to cancel &quot;nested()&quot;, or</span>
<span class="c1"># can simply be awaited to wait until it is complete:</span>
<span class="k">await</span> <span class="n">task</span>
<span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">())</span>
</pre></div>
</div>
<p class="rubric">Futures</p>
<p><a class="reference internal" href="asyncio-future.html#asyncio.Future" title="asyncio.Future"><code class="xref py py-class docutils literal notranslate"><span class="pre">Future</span></code></a> 是一种特殊的 <strong>低层级</strong> 可等待对象,表示一个异步操作的 <strong>最终结果</strong></p>
<p>当一个 Future 对象 <em>被等待</em>,这意味着协程将保持等待直到该 Future 对象在其他地方操作完毕。</p>
<p>在 asyncio 中需要 Future 对象以便允许通过 async/await 使用基于回调的代码。</p>
<p>通常情况下 <strong>没有必要</strong> 在应用层级的代码中创建 Future 对象。</p>
<p>Future 对象有时会由库和某些 asyncio API 暴露给用户,用作可等待对象:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="k">await</span> <span class="n">function_that_returns_a_future_object</span><span class="p">()</span>
<span class="c1"># this is also valid:</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">function_that_returns_a_future_object</span><span class="p">(),</span>
<span class="n">some_python_coroutine</span><span class="p">()</span>
<span class="p">)</span>
</pre></div>
</div>
<p>一个很好的返回对象的低层级函数的示例是 <a class="reference internal" href="asyncio-eventloop.html#asyncio.loop.run_in_executor" title="asyncio.loop.run_in_executor"><code class="xref py py-meth docutils literal notranslate"><span class="pre">loop.run_in_executor()</span></code></a></p>
</section>
<section id="running-an-asyncio-program">
<h2><a class="toc-backref" href="#id4">运行 asyncio 程序</a><a class="headerlink" href="#running-an-asyncio-program" title="永久链接至标题"></a></h2>
<dl class="function">
<dt id="asyncio.run">
<code class="sig-prename descclassname">asyncio.</code><code class="sig-name descname">run</code><span class="sig-paren">(</span><em class="sig-param">coro</em>, <em class="sig-param">*</em>, <em class="sig-param">debug=False</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.run" title="永久链接至目标"></a></dt>
<dd><p>执行 <a class="reference internal" href="../glossary.html#term-coroutine"><span class="xref std std-term">coroutine</span></a> <em>coro</em> 并返回结果。</p>
<p>此函数运行传入的协程,负责管理 asyncio 事件循环并 <em>完结异步生成器</em></p>
<p>当有其他 asyncio 事件循环在同一线程中运行时,此函数不能被调用。</p>
<p>如果 <em>debug</em><code class="docutils literal notranslate"><span class="pre">True</span></code>,事件循环将以调试模式运行。</p>
<p>此函数总是会创建一个新的事件循环并在结束时关闭之。它应当被用作 asyncio 程序的主入口点,理想情况下应当只被调用一次。</p>
<p>示例:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="k">await</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="nb">print</span><span class="p">(</span><span class="s1">&#39;hello&#39;</span><span class="p">)</span>
<span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">())</span>
</pre></div>
</div>
<div class="versionadded">
<p><span class="versionmodified added">3.7 新版功能.</span></p>
</div>
<div class="admonition note">
<p class="admonition-title">注解</p>
<p><code class="docutils literal notranslate"><span class="pre">asyncio.run()</span></code> 的源代码可以在 <a class="reference external" href="https://github.com/python/cpython/tree/3.8/Lib/asyncio/runners.py">Lib/asyncio/runners.py</a> 中找到。</p>
</div>
</dd></dl>
</section>
<section id="creating-tasks">
<h2><a class="toc-backref" href="#id5">创建任务</a><a class="headerlink" href="#creating-tasks" title="永久链接至标题"></a></h2>
<dl class="function">
<dt id="asyncio.create_task">
<code class="sig-prename descclassname">asyncio.</code><code class="sig-name descname">create_task</code><span class="sig-paren">(</span><em class="sig-param">coro</em>, <em class="sig-param">*</em>, <em class="sig-param">name=None</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.create_task" title="永久链接至目标"></a></dt>
<dd><p><em>coro</em> <a class="reference internal" href="#coroutine"><span class="std std-ref">协程</span></a> 封装为一个 <a class="reference internal" href="#asyncio.Task" title="asyncio.Task"><code class="xref py py-class docutils literal notranslate"><span class="pre">Task</span></code></a> 并调度其执行。返回 Task 对象。</p>
<p><em>name</em> 不为 <code class="docutils literal notranslate"><span class="pre">None</span></code>,它将使用 <a class="reference internal" href="#asyncio.Task.set_name" title="asyncio.Task.set_name"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Task.set_name()</span></code></a> 来设为任务的名称。</p>
<p>该任务会在 <a class="reference internal" href="asyncio-eventloop.html#asyncio.get_running_loop" title="asyncio.get_running_loop"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_running_loop()</span></code></a> 返回的循环中执行,如果当前线程没有在运行的循环则会引发 <a class="reference internal" href="exceptions.html#RuntimeError" title="RuntimeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">RuntimeError</span></code></a></p>
<p>此函数 <strong>在 Python 3.7 中被加入</strong>。在 Python 3.7 之前,可以改用低层级的 <a class="reference internal" href="asyncio-future.html#asyncio.ensure_future" title="asyncio.ensure_future"><code class="xref py py-func docutils literal notranslate"><span class="pre">asyncio.ensure_future()</span></code></a> 函数。</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">def</span> <span class="nf">coro</span><span class="p">():</span>
<span class="o">...</span>
<span class="c1"># In Python 3.7+</span>
<span class="n">task</span> <span class="o">=</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">create_task</span><span class="p">(</span><span class="n">coro</span><span class="p">())</span>
<span class="o">...</span>
<span class="c1"># This works in all Python versions but is less readable</span>
<span class="n">task</span> <span class="o">=</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">ensure_future</span><span class="p">(</span><span class="n">coro</span><span class="p">())</span>
<span class="o">...</span>
</pre></div>
</div>
<div class="versionadded">
<p><span class="versionmodified added">3.7 新版功能.</span></p>
</div>
<div class="versionchanged">
<p><span class="versionmodified changed">在 3.8 版更改: </span>添加了 <code class="docutils literal notranslate"><span class="pre">name</span></code> 形参。</p>
</div>
</dd></dl>
</section>
<section id="sleeping">
<h2><a class="toc-backref" href="#id6">休眠</a><a class="headerlink" href="#sleeping" title="永久链接至标题"></a></h2>
<dl class="function">
<dt id="asyncio.sleep">
<em class="property">coroutine </em><code class="sig-prename descclassname">asyncio.</code><code class="sig-name descname">sleep</code><span class="sig-paren">(</span><em class="sig-param">delay</em>, <em class="sig-param">result=None</em>, <em class="sig-param">*</em>, <em class="sig-param">loop=None</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.sleep" title="永久链接至目标"></a></dt>
<dd><p>阻塞 <em>delay</em> 指定的秒数。</p>
<p>如果指定了 <em>result</em>,则当协程完成时将其返回给调用者。</p>
<p><code class="docutils literal notranslate"><span class="pre">sleep()</span></code> 总是会挂起当前任务,以允许其他任务运行。</p>
<div class="deprecated-removed">
<p><span class="versionmodified">Deprecated since version 3.8, will be removed in version 3.10: </span><em>loop</em> 形参。</p>
</div>
<p id="asyncio-example-sleep">以下协程示例运行 5 秒,每秒显示一次当前日期:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">asyncio</span>
<span class="kn">import</span> <span class="nn">datetime</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">display_date</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_running_loop</span><span class="p">()</span>
<span class="n">end_time</span> <span class="o">=</span> <span class="n">loop</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">+</span> <span class="mf">5.0</span>
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">())</span>
<span class="k">if</span> <span class="p">(</span><span class="n">loop</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">+</span> <span class="mf">1.0</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="n">end_time</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">await</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="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">display_date</span><span class="p">())</span>
</pre></div>
</div>
</dd></dl>
</section>
<section id="running-tasks-concurrently">
<h2><a class="toc-backref" href="#id7">并发运行任务</a><a class="headerlink" href="#running-tasks-concurrently" title="永久链接至标题"></a></h2>
<dl class="function">
<dt id="asyncio.gather">
<em class="property">awaitable </em><code class="sig-prename descclassname">asyncio.</code><code class="sig-name descname">gather</code><span class="sig-paren">(</span><em class="sig-param">*aws</em>, <em class="sig-param">loop=None</em>, <em class="sig-param">return_exceptions=False</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.gather" title="永久链接至目标"></a></dt>
<dd><p><em>并发</em> 运行 <em>aws</em> 序列中的 <a class="reference internal" href="#asyncio-awaitables"><span class="std std-ref">可等待对象</span></a></p>
<p>如果 <em>aws</em> 中的某个可等待对象为协程,它将自动被作为一个任务调度。</p>
<p>如果所有可等待对象都成功完成,结果将是一个由所有返回值聚合而成的列表。结果值的顺序与 <em>aws</em> 中可等待对象的顺序一致。</p>
<p>如果 <em>return_exceptions</em><code class="docutils literal notranslate"><span class="pre">False</span></code> (默认),所引发的首个异常会立即传播给等待 <code class="docutils literal notranslate"><span class="pre">gather()</span></code> 的任务。<em>aws</em> 序列中的其他可等待对象 <strong>不会被取消</strong> 并将继续运行。</p>
<p>如果 <em>return_exceptions</em><code class="docutils literal notranslate"><span class="pre">True</span></code>,异常会和成功的结果一样处理,并聚合至结果列表。</p>
<p>如果 <code class="docutils literal notranslate"><span class="pre">gather()</span></code> <em>被取消</em>,所有被提交 (尚未完成) 的可等待对象也会 <em>被取消</em></p>
<p>如果 <em>aws</em> 序列中的任一 Task 或 Future 对象 <em>被取消</em>,它将被当作引发了 <a class="reference internal" href="asyncio-exceptions.html#asyncio.CancelledError" title="asyncio.CancelledError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">CancelledError</span></code></a> 一样处理 -- 在此情况下 <code class="docutils literal notranslate"><span class="pre">gather()</span></code> 调用 <strong>不会</strong> 被取消。这是为了防止一个已提交的 Task/Future 被取消导致其他 Tasks/Future 也被取消。</p>
<div class="deprecated-removed">
<p><span class="versionmodified">Deprecated since version 3.8, will be removed in version 3.10: </span><em>loop</em> 形参。</p>
</div>
<p id="asyncio-example-gather">示例:</p>
<div class="highlight-python3 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">factorial</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">number</span><span class="p">):</span>
<span class="n">f</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">number</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Task </span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2">: Compute factorial(</span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">)...&quot;</span><span class="p">)</span>
<span class="k">await</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="n">f</span> <span class="o">*=</span> <span class="n">i</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Task </span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2">: factorial(</span><span class="si">{</span><span class="n">number</span><span class="si">}</span><span class="s2">) = </span><span class="si">{</span><span class="n">f</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="c1"># Schedule three calls *concurrently*:</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">factorial</span><span class="p">(</span><span class="s2">&quot;A&quot;</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span>
<span class="n">factorial</span><span class="p">(</span><span class="s2">&quot;B&quot;</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span>
<span class="n">factorial</span><span class="p">(</span><span class="s2">&quot;C&quot;</span><span class="p">,</span> <span class="mi">4</span><span class="p">),</span>
<span class="p">)</span>
<span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">())</span>
<span class="c1"># Expected output:</span>
<span class="c1">#</span>
<span class="c1"># Task A: Compute factorial(2)...</span>
<span class="c1"># Task B: Compute factorial(2)...</span>
<span class="c1"># Task C: Compute factorial(2)...</span>
<span class="c1"># Task A: factorial(2) = 2</span>
<span class="c1"># Task B: Compute factorial(3)...</span>
<span class="c1"># Task C: Compute factorial(3)...</span>
<span class="c1"># Task B: factorial(3) = 6</span>
<span class="c1"># Task C: Compute factorial(4)...</span>
<span class="c1"># Task C: factorial(4) = 24</span>
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">注解</p>
<p>如果 <em>return_exceptions</em> 为 False则在 gather() 被标记为已完成后取消它将不会取消任何已提交的可等待对象。 例如在将一个异常传播给调用者之后gather 可被标记为已完成,因此,在从 gather 捕获一个(由可等待对象所引发的)异常之后调用 <code class="docutils literal notranslate"><span class="pre">gather.cancel()</span></code> 将不会取消任何其他可等待对象。</p>
</div>
<div class="versionchanged">
<p><span class="versionmodified changed">在 3.7 版更改: </span>如果 <em>gather</em> 本身被取消,则无论 <em>return_exceptions</em> 取值为何,消息都会被传播。</p>
</div>
</dd></dl>
</section>
<section id="shielding-from-cancellation">
<h2><a class="toc-backref" href="#id8">屏蔽取消操作</a><a class="headerlink" href="#shielding-from-cancellation" title="永久链接至标题"></a></h2>
<dl class="function">
<dt id="asyncio.shield">
<em class="property">awaitable </em><code class="sig-prename descclassname">asyncio.</code><code class="sig-name descname">shield</code><span class="sig-paren">(</span><em class="sig-param">aw</em>, <em class="sig-param">*</em>, <em class="sig-param">loop=None</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.shield" title="永久链接至目标"></a></dt>
<dd><p>保护一个 <a class="reference internal" href="#asyncio-awaitables"><span class="std std-ref">可等待对象</span></a> 防止其被 <a class="reference internal" href="#asyncio.Task.cancel" title="asyncio.Task.cancel"><code class="xref py py-meth docutils literal notranslate"><span class="pre">取消</span></code></a></p>
<p>如果 <em>aw</em> 是一个协程,它将自动被作为任务调度。</p>
<p>以下语句:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">res</span> <span class="o">=</span> <span class="k">await</span> <span class="n">shield</span><span class="p">(</span><span class="n">something</span><span class="p">())</span>
</pre></div>
</div>
<p>相当于:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">res</span> <span class="o">=</span> <span class="k">await</span> <span class="n">something</span><span class="p">()</span>
</pre></div>
</div>
<p><em>不同之处</em> 在于如果包含它的协程被取消,在 <code class="docutils literal notranslate"><span class="pre">something()</span></code> 中运行的任务不会被取消。从 <code class="docutils literal notranslate"><span class="pre">something()</span></code> 的角度看来,取消操作并没有发生。然而其调用者已被取消,因此 &quot;await&quot; 表达式仍然会引发 <a class="reference internal" href="asyncio-exceptions.html#asyncio.CancelledError" title="asyncio.CancelledError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">CancelledError</span></code></a></p>
<p>如果通过其他方式取消 <code class="docutils literal notranslate"><span class="pre">something()</span></code> (例如在其内部操作) 则 <code class="docutils literal notranslate"><span class="pre">shield()</span></code> 也会取消。</p>
<p>如果希望完全忽略取消操作 (不推荐) 则 <code class="docutils literal notranslate"><span class="pre">shield()</span></code> 函数需要配合一个 try/except 代码段,如下所示:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
<span class="n">res</span> <span class="o">=</span> <span class="k">await</span> <span class="n">shield</span><span class="p">(</span><span class="n">something</span><span class="p">())</span>
<span class="k">except</span> <span class="n">CancelledError</span><span class="p">:</span>
<span class="n">res</span> <span class="o">=</span> <span class="kc">None</span>
</pre></div>
</div>
<div class="deprecated-removed">
<p><span class="versionmodified">Deprecated since version 3.8, will be removed in version 3.10: </span><em>loop</em> 形参。</p>
</div>
</dd></dl>
</section>
<section id="timeouts">
<h2><a class="toc-backref" href="#id9">超时</a><a class="headerlink" href="#timeouts" title="永久链接至标题"></a></h2>
<dl class="function">
<dt id="asyncio.wait_for">
<em class="property">coroutine </em><code class="sig-prename descclassname">asyncio.</code><code class="sig-name descname">wait_for</code><span class="sig-paren">(</span><em class="sig-param">aw</em>, <em class="sig-param">timeout</em>, <em class="sig-param">*</em>, <em class="sig-param">loop=None</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.wait_for" title="永久链接至目标"></a></dt>
<dd><p>等待 <em>aw</em> <a class="reference internal" href="#asyncio-awaitables"><span class="std std-ref">可等待对象</span></a> 完成,指定 timeout 秒数后超时。</p>
<p>如果 <em>aw</em> 是一个协程,它将自动被作为任务调度。</p>
<p><em>timeout</em> 可以为 <code class="docutils literal notranslate"><span class="pre">None</span></code>,也可以为 float 或 int 型数值表示的等待秒数。如果 <em>timeout</em><code class="docutils literal notranslate"><span class="pre">None</span></code>,则等待直到完成。</p>
<p>如果发生超时,任务将取消并引发 <a class="reference internal" href="asyncio-exceptions.html#asyncio.TimeoutError" title="asyncio.TimeoutError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">asyncio.TimeoutError</span></code></a>.</p>
<p>要避免任务 <a class="reference internal" href="#asyncio.Task.cancel" title="asyncio.Task.cancel"><code class="xref py py-meth docutils literal notranslate"><span class="pre">取消</span></code></a>,可以加上 <a class="reference internal" href="#asyncio.shield" title="asyncio.shield"><code class="xref py py-func docutils literal notranslate"><span class="pre">shield()</span></code></a></p>
<p>函数将等待直到目标对象确实被取消,所以总等待时间可能超过 <em>timeout</em> 指定的秒数。</p>
<p>如果等待被取消,则 <em>aw</em> 指定的对象也会被取消。</p>
<div class="deprecated-removed">
<p><span class="versionmodified">Deprecated since version 3.8, will be removed in version 3.10: </span><em>loop</em> 形参。</p>
</div>
<p id="asyncio-example-waitfor">示例:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">def</span> <span class="nf">eternity</span><span class="p">():</span>
<span class="c1"># Sleep for one hour</span>
<span class="k">await</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">3600</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;yay!&#39;</span><span class="p">)</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="c1"># Wait for at most 1 second</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">await</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">wait_for</span><span class="p">(</span><span class="n">eternity</span><span class="p">(),</span> <span class="n">timeout</span><span class="o">=</span><span class="mf">1.0</span><span class="p">)</span>
<span class="k">except</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">TimeoutError</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;timeout!&#39;</span><span class="p">)</span>
<span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">())</span>
<span class="c1"># Expected output:</span>
<span class="c1">#</span>
<span class="c1"># timeout!</span>
</pre></div>
</div>
<div class="versionchanged">
<p><span class="versionmodified changed">在 3.7 版更改: </span><em>aw</em> 因超时被取消,<code class="docutils literal notranslate"><span class="pre">wait_for</span></code> 会等待 <em>aw</em> 被取消。之前版本则将立即引发 <a class="reference internal" href="asyncio-exceptions.html#asyncio.TimeoutError" title="asyncio.TimeoutError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">asyncio.TimeoutError</span></code></a></p>
</div>
</dd></dl>
</section>
<section id="waiting-primitives">
<h2><a class="toc-backref" href="#id10">简单等待</a><a class="headerlink" href="#waiting-primitives" title="永久链接至标题"></a></h2>
<dl class="function">
<dt id="asyncio.wait">
<em class="property">coroutine </em><code class="sig-prename descclassname">asyncio.</code><code class="sig-name descname">wait</code><span class="sig-paren">(</span><em class="sig-param">aws</em>, <em class="sig-param">*</em>, <em class="sig-param">loop=None</em>, <em class="sig-param">timeout=None</em>, <em class="sig-param">return_when=ALL_COMPLETED</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.wait" title="永久链接至目标"></a></dt>
<dd><p>并发地运行 <em>aws</em> 可迭代对象中的 <a class="reference internal" href="#asyncio-awaitables"><span class="std std-ref">可等待对象</span></a> 并进入阻塞状态直到满足 <em>return_when</em> 所指定的条件。</p>
<p>返回两个 Task/Future 集合: <code class="docutils literal notranslate"><span class="pre">(done,</span> <span class="pre">pending)</span></code></p>
<p>用法:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">done</span><span class="p">,</span> <span class="n">pending</span> <span class="o">=</span> <span class="k">await</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">wait</span><span class="p">(</span><span class="n">aws</span><span class="p">)</span>
</pre></div>
</div>
<p>如指定 <em>timeout</em> (float 或 int 类型) 则它将被用于控制返回之前等待的最长秒数。</p>
<p>请注意此函数不会引发 <a class="reference internal" href="asyncio-exceptions.html#asyncio.TimeoutError" title="asyncio.TimeoutError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">asyncio.TimeoutError</span></code></a>。当超时发生时,未完成的 Future 或 Task 将在指定秒数后被返回。</p>
<p><em>return_when</em> 指定此函数应在何时返回。它必须为以下常数之一:</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 42%" />
<col style="width: 58%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head"><p>常量</p></th>
<th class="head"><p>描述</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p><code class="xref py py-const docutils literal notranslate"><span class="pre">FIRST_COMPLETED</span></code></p></td>
<td><p>函数将在任意可等待对象结束或取消时返回。</p></td>
</tr>
<tr class="row-odd"><td><p><code class="xref py py-const docutils literal notranslate"><span class="pre">FIRST_EXCEPTION</span></code></p></td>
<td><p>函数将在任意可等待对象因引发异常而结束时返回。当没有引发任何异常时它就相当于 <code class="xref py py-const docutils literal notranslate"><span class="pre">ALL_COMPLETED</span></code></p></td>
</tr>
<tr class="row-even"><td><p><code class="xref py py-const docutils literal notranslate"><span class="pre">ALL_COMPLETED</span></code></p></td>
<td><p>函数将在所有可等待对象结束或取消时返回。</p></td>
</tr>
</tbody>
</table>
<p><a class="reference internal" href="#asyncio.wait_for" title="asyncio.wait_for"><code class="xref py py-func docutils literal notranslate"><span class="pre">wait_for()</span></code></a> 不同,<code class="docutils literal notranslate"><span class="pre">wait()</span></code> 在超时发生时不会取消可等待对象。</p>
<div class="deprecated">
<p><span class="versionmodified deprecated">3.8 版后已移除: </span>如果 <em>aws</em> 中的某个可等待对象为协程,它将自动被作为任务调度。直接向 <code class="docutils literal notranslate"><span class="pre">wait()</span></code> 传入协程对象已弃用,因为这会导致 <a class="reference internal" href="#asyncio-example-wait-coroutine"><span class="std std-ref">令人迷惑的行为</span></a></p>
</div>
<div class="deprecated-removed">
<p><span class="versionmodified">Deprecated since version 3.8, will be removed in version 3.10: </span><em>loop</em> 形参。</p>
</div>
<div class="admonition note" id="asyncio-example-wait-coroutine">
<p class="admonition-title">注解</p>
<p><code class="docutils literal notranslate"><span class="pre">wait()</span></code> 会自动以任务的形式调度协程,之后将以 <code class="docutils literal notranslate"><span class="pre">(done,</span> <span class="pre">pending)</span></code> 集合形式返回显式创建的任务对象。因此以下代码并不会有预期的行为:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">def</span> <span class="nf">foo</span><span class="p">():</span>
<span class="k">return</span> <span class="mi">42</span>
<span class="n">coro</span> <span class="o">=</span> <span class="n">foo</span><span class="p">()</span>
<span class="n">done</span><span class="p">,</span> <span class="n">pending</span> <span class="o">=</span> <span class="k">await</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">wait</span><span class="p">({</span><span class="n">coro</span><span class="p">})</span>
<span class="k">if</span> <span class="n">coro</span> <span class="ow">in</span> <span class="n">done</span><span class="p">:</span>
<span class="c1"># This branch will never be run!</span>
</pre></div>
</div>
<p>以上代码段的修正方法如下:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">def</span> <span class="nf">foo</span><span class="p">():</span>
<span class="k">return</span> <span class="mi">42</span>
<span class="n">task</span> <span class="o">=</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">create_task</span><span class="p">(</span><span class="n">foo</span><span class="p">())</span>
<span class="n">done</span><span class="p">,</span> <span class="n">pending</span> <span class="o">=</span> <span class="k">await</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">wait</span><span class="p">({</span><span class="n">task</span><span class="p">})</span>
<span class="k">if</span> <span class="n">task</span> <span class="ow">in</span> <span class="n">done</span><span class="p">:</span>
<span class="c1"># Everything will work as expected now.</span>
</pre></div>
</div>
</div>
<div class="deprecated">
<p><span class="versionmodified deprecated">3.8 版后已移除: </span>直接向 <code class="docutils literal notranslate"><span class="pre">wait()</span></code> 传入协程对象的方式已弃用。</p>
</div>
</dd></dl>
<dl class="function">
<dt id="asyncio.as_completed">
<code class="sig-prename descclassname">asyncio.</code><code class="sig-name descname">as_completed</code><span class="sig-paren">(</span><em class="sig-param">aws</em>, <em class="sig-param">*</em>, <em class="sig-param">loop=None</em>, <em class="sig-param">timeout=None</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.as_completed" title="永久链接至目标"></a></dt>
<dd><p>并发地运行 <em>aws</em> 可迭代对象中的 <a class="reference internal" href="#asyncio-awaitables"><span class="std std-ref">可等待对象</span></a>。 返回一个协程的迭代器。 所返回的每个协程可被等待以从剩余的可等待对象的可迭代对象中获得最早的下一个结果。</p>
<p>如果在所有 Future 对象完成前发生超时则将引发 <a class="reference internal" href="asyncio-exceptions.html#asyncio.TimeoutError" title="asyncio.TimeoutError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">asyncio.TimeoutError</span></code></a></p>
<div class="deprecated-removed">
<p><span class="versionmodified">Deprecated since version 3.8, will be removed in version 3.10: </span><em>loop</em> 形参。</p>
</div>
<p>示例:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">coro</span> <span class="ow">in</span> <span class="n">as_completed</span><span class="p">(</span><span class="n">aws</span><span class="p">):</span>
<span class="n">earliest_result</span> <span class="o">=</span> <span class="k">await</span> <span class="n">coro</span>
<span class="c1"># ...</span>
</pre></div>
</div>
</dd></dl>
</section>
<section id="scheduling-from-other-threads">
<h2><a class="toc-backref" href="#id11">跨线程调度</a><a class="headerlink" href="#scheduling-from-other-threads" title="永久链接至标题"></a></h2>
<dl class="function">
<dt id="asyncio.run_coroutine_threadsafe">
<code class="sig-prename descclassname">asyncio.</code><code class="sig-name descname">run_coroutine_threadsafe</code><span class="sig-paren">(</span><em class="sig-param">coro</em>, <em class="sig-param">loop</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.run_coroutine_threadsafe" title="永久链接至目标"></a></dt>
<dd><p>向指定事件循环提交一个协程。(线程安全)</p>
<p>返回一个 <a class="reference internal" href="concurrent.futures.html#concurrent.futures.Future" title="concurrent.futures.Future"><code class="xref py py-class docutils literal notranslate"><span class="pre">concurrent.futures.Future</span></code></a> 以等待来自其他 OS 线程的结果。</p>
<p>此函数应该从另一个 OS 线程中调用,而非事件循环运行所在线程。示例:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="c1"># Create a coroutine</span>
<span class="n">coro</span> <span class="o">=</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="n">result</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span>
<span class="c1"># Submit the coroutine to a given loop</span>
<span class="n">future</span> <span class="o">=</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">run_coroutine_threadsafe</span><span class="p">(</span><span class="n">coro</span><span class="p">,</span> <span class="n">loop</span><span class="p">)</span>
<span class="c1"># Wait for the result with an optional timeout argument</span>
<span class="k">assert</span> <span class="n">future</span><span class="o">.</span><span class="n">result</span><span class="p">(</span><span class="n">timeout</span><span class="p">)</span> <span class="o">==</span> <span class="mi">3</span>
</pre></div>
</div>
<p>如果在协程内产生了异常,将会通知返回的 Future 对象。它也可被用来取消事件循环中的任务:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">future</span><span class="o">.</span><span class="n">result</span><span class="p">(</span><span class="n">timeout</span><span class="p">)</span>
<span class="k">except</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">TimeoutError</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;The coroutine took too long, cancelling the task...&#39;</span><span class="p">)</span>
<span class="n">future</span><span class="o">.</span><span class="n">cancel</span><span class="p">()</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;The coroutine raised an exception: </span><span class="si">{</span><span class="n">exc</span><span class="si">!r}</span><span class="s1">&#39;</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;The coroutine returned: </span><span class="si">{</span><span class="n">result</span><span class="si">!r}</span><span class="s1">&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>参见 <a class="reference internal" href="asyncio-dev.html#asyncio-multithreading"><span class="std std-ref">concurrency and multithreading</span></a> 部分的文档。</p>
<p>不同于其他 asyncio 函数,此函数要求显式地传入 <em>loop</em> 参数。</p>
<div class="versionadded">
<p><span class="versionmodified added">3.5.1 新版功能.</span></p>
</div>
</dd></dl>
</section>
<section id="introspection">
<h2><a class="toc-backref" href="#id12">内省</a><a class="headerlink" href="#introspection" title="永久链接至标题"></a></h2>
<dl class="function">
<dt id="asyncio.current_task">
<code class="sig-prename descclassname">asyncio.</code><code class="sig-name descname">current_task</code><span class="sig-paren">(</span><em class="sig-param">loop=None</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.current_task" title="永久链接至目标"></a></dt>
<dd><p>返回当前运行的 <a class="reference internal" href="#asyncio.Task" title="asyncio.Task"><code class="xref py py-class docutils literal notranslate"><span class="pre">Task</span></code></a> 实例,如果没有正在运行的任务则返回 <code class="docutils literal notranslate"><span class="pre">None</span></code></p>
<p>如果 <em>loop</em><code class="docutils literal notranslate"><span class="pre">None</span></code> 则会使用 <a class="reference internal" href="asyncio-eventloop.html#asyncio.get_running_loop" title="asyncio.get_running_loop"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_running_loop()</span></code></a> 获取当前事件循环。</p>
<div class="versionadded">
<p><span class="versionmodified added">3.7 新版功能.</span></p>
</div>
</dd></dl>
<dl class="function">
<dt id="asyncio.all_tasks">
<code class="sig-prename descclassname">asyncio.</code><code class="sig-name descname">all_tasks</code><span class="sig-paren">(</span><em class="sig-param">loop=None</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.all_tasks" title="永久链接至目标"></a></dt>
<dd><p>返回事件循环所运行的未完成的 <a class="reference internal" href="#asyncio.Task" title="asyncio.Task"><code class="xref py py-class docutils literal notranslate"><span class="pre">Task</span></code></a> 对象的集合。</p>
<p>如果 <em>loop</em><code class="docutils literal notranslate"><span class="pre">None</span></code>,则会使用 <a class="reference internal" href="asyncio-eventloop.html#asyncio.get_running_loop" title="asyncio.get_running_loop"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_running_loop()</span></code></a> 获取当前事件循环。</p>
<div class="versionadded">
<p><span class="versionmodified added">3.7 新版功能.</span></p>
</div>
</dd></dl>
</section>
<section id="task-object">
<h2><a class="toc-backref" href="#id13">Task 对象</a><a class="headerlink" href="#task-object" title="永久链接至标题"></a></h2>
<dl class="class">
<dt id="asyncio.Task">
<em class="property">class </em><code class="sig-prename descclassname">asyncio.</code><code class="sig-name descname">Task</code><span class="sig-paren">(</span><em class="sig-param">coro</em>, <em class="sig-param">*</em>, <em class="sig-param">loop=None</em>, <em class="sig-param">name=None</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.Task" title="永久链接至目标"></a></dt>
<dd><p>一个与 <a class="reference internal" href="asyncio-future.html#asyncio.Future" title="asyncio.Future"><code class="xref py py-class docutils literal notranslate"><span class="pre">Future</span> <span class="pre">类似</span></code></a> 的对象,可运行 Python <a class="reference internal" href="#coroutine"><span class="std std-ref">协程</span></a>。非线程安全。</p>
<p>Task 对象被用来在事件循环中运行协程。如果一个协程在等待一个 Future 对象Task 对象会挂起该协程的执行并等待该 Future 对象完成。当该 Future 对象 <em>完成</em>,被打包的协程将恢复执行。</p>
<p>事件循环使用协同日程调度: 一个事件循环每次运行一个 Task 对象。而一个 Task 对象会等待一个 Future 对象完成,该事件循环会运行其他 Task、回调或执行 IO 操作。</p>
<p>使用高层级的 <a class="reference internal" href="#asyncio.create_task" title="asyncio.create_task"><code class="xref py py-func docutils literal notranslate"><span class="pre">asyncio.create_task()</span></code></a> 函数来创建 Task 对象,也可用低层级的 <a class="reference internal" href="asyncio-eventloop.html#asyncio.loop.create_task" title="asyncio.loop.create_task"><code class="xref py py-meth docutils literal notranslate"><span class="pre">loop.create_task()</span></code></a><a class="reference internal" href="asyncio-future.html#asyncio.ensure_future" title="asyncio.ensure_future"><code class="xref py py-func docutils literal notranslate"><span class="pre">ensure_future()</span></code></a> 函数。不建议手动实例化 Task 对象。</p>
<p>要取消一个正在运行的 Task 对象可使用 <a class="reference internal" href="#asyncio.Task.cancel" title="asyncio.Task.cancel"><code class="xref py py-meth docutils literal notranslate"><span class="pre">cancel()</span></code></a> 方法。调用此方法将使该 Task 对象抛出一个 <a class="reference internal" href="asyncio-exceptions.html#asyncio.CancelledError" title="asyncio.CancelledError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">CancelledError</span></code></a> 异常给打包的协程。如果取消期间一个协程正在对 Future 对象执行 await该 Future 对象也将被取消。</p>
<p><a class="reference internal" href="#asyncio.Task.cancelled" title="asyncio.Task.cancelled"><code class="xref py py-meth docutils literal notranslate"><span class="pre">cancelled()</span></code></a> 可被用来检测 Task 对象是否被取消。如果打包的协程没有抑制 <a class="reference internal" href="asyncio-exceptions.html#asyncio.CancelledError" title="asyncio.CancelledError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">CancelledError</span></code></a> 异常并且确实被取消,该方法将返回 <code class="docutils literal notranslate"><span class="pre">True</span></code></p>
<p><a class="reference internal" href="#asyncio.Task" title="asyncio.Task"><code class="xref py py-class docutils literal notranslate"><span class="pre">asyncio.Task</span></code></a><a class="reference internal" href="asyncio-future.html#asyncio.Future" title="asyncio.Future"><code class="xref py py-class docutils literal notranslate"><span class="pre">Future</span></code></a> 继承了其除 <a class="reference internal" href="asyncio-future.html#asyncio.Future.set_result" title="asyncio.Future.set_result"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Future.set_result()</span></code></a><a class="reference internal" href="asyncio-future.html#asyncio.Future.set_exception" title="asyncio.Future.set_exception"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Future.set_exception()</span></code></a> 以外的所有 API。</p>
<p>Task 对象支持 <a class="reference internal" href="contextvars.html#module-contextvars" title="contextvars: Context Variables"><code class="xref py py-mod docutils literal notranslate"><span class="pre">contextvars</span></code></a> 模块。当一个 Task 对象被创建,它将复制当前上下文,然后在复制的上下文中运行其协程。</p>
<div class="versionchanged">
<p><span class="versionmodified changed">在 3.7 版更改: </span>加入对 <a class="reference internal" href="contextvars.html#module-contextvars" title="contextvars: Context Variables"><code class="xref py py-mod docutils literal notranslate"><span class="pre">contextvars</span></code></a> 模块的支持。</p>
</div>
<div class="versionchanged">
<p><span class="versionmodified changed">在 3.8 版更改: </span>添加了 <code class="docutils literal notranslate"><span class="pre">name</span></code> 形参。</p>
</div>
<div class="deprecated-removed">
<p><span class="versionmodified">Deprecated since version 3.8, will be removed in version 3.10: </span><em>loop</em> 形参。</p>
</div>
<dl class="method">
<dt id="asyncio.Task.cancel">
<code class="sig-name descname">cancel</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.Task.cancel" title="永久链接至目标"></a></dt>
<dd><p>请求取消 Task 对象。</p>
<p>这将安排在下一轮事件循环中抛出一个 <a class="reference internal" href="asyncio-exceptions.html#asyncio.CancelledError" title="asyncio.CancelledError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">CancelledError</span></code></a> 异常给被封包的协程。</p>
<p>协程在之后有机会进行清理甚至使用 <a class="reference internal" href="../reference/compound_stmts.html#try"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">try</span></code></a> ... ... <code class="docutils literal notranslate"><span class="pre">except</span> <span class="pre">CancelledError</span></code> ... <a class="reference internal" href="../reference/compound_stmts.html#finally"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">finally</span></code></a> 代码块抑制异常来拒绝请求。不同于 <a class="reference internal" href="asyncio-future.html#asyncio.Future.cancel" title="asyncio.Future.cancel"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Future.cancel()</span></code></a><a class="reference internal" href="#asyncio.Task.cancel" title="asyncio.Task.cancel"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Task.cancel()</span></code></a> 不保证 Task 会被取消,虽然抑制完全取消并不常见,也很不鼓励这样做。</p>
<p id="asyncio-example-task-cancel">以下示例演示了协程是如何侦听取消请求的:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">def</span> <span class="nf">cancel_me</span><span class="p">():</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;cancel_me(): before sleep&#39;</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="c1"># Wait for 1 hour</span>
<span class="k">await</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">3600</span><span class="p">)</span>
<span class="k">except</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">CancelledError</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;cancel_me(): cancel sleep&#39;</span><span class="p">)</span>
<span class="k">raise</span>
<span class="k">finally</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;cancel_me(): after sleep&#39;</span><span class="p">)</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="c1"># Create a &quot;cancel_me&quot; Task</span>
<span class="n">task</span> <span class="o">=</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">create_task</span><span class="p">(</span><span class="n">cancel_me</span><span class="p">())</span>
<span class="c1"># Wait for 1 second</span>
<span class="k">await</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="n">task</span><span class="o">.</span><span class="n">cancel</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">await</span> <span class="n">task</span>
<span class="k">except</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">CancelledError</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;main(): cancel_me is cancelled now&quot;</span><span class="p">)</span>
<span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">())</span>
<span class="c1"># Expected output:</span>
<span class="c1">#</span>
<span class="c1"># cancel_me(): before sleep</span>
<span class="c1"># cancel_me(): cancel sleep</span>
<span class="c1"># cancel_me(): after sleep</span>
<span class="c1"># main(): cancel_me is cancelled now</span>
</pre></div>
</div>
</dd></dl>
<dl class="method">
<dt id="asyncio.Task.cancelled">
<code class="sig-name descname">cancelled</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.Task.cancelled" title="永久链接至目标"></a></dt>
<dd><p>如果 Task 对象 <em>被取消</em> 则返回 <code class="docutils literal notranslate"><span class="pre">True</span></code></p>
<p>当使用 <a class="reference internal" href="#asyncio.Task.cancel" title="asyncio.Task.cancel"><code class="xref py py-meth docutils literal notranslate"><span class="pre">cancel()</span></code></a> 发出取消请求时 Task 会被 <em>取消</em>,其封包的协程将传播被抛入的 <a class="reference internal" href="asyncio-exceptions.html#asyncio.CancelledError" title="asyncio.CancelledError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">CancelledError</span></code></a> 异常。</p>
</dd></dl>
<dl class="method">
<dt id="asyncio.Task.done">
<code class="sig-name descname">done</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.Task.done" title="永久链接至目标"></a></dt>
<dd><p>如果 Task 对象 <em>已完成</em> 则返回 <code class="docutils literal notranslate"><span class="pre">True</span></code></p>
<p>当 Task 所封包的协程返回一个值、引发一个异常或 Task 本身被取消时,则会被认为 <em>已完成</em></p>
</dd></dl>
<dl class="method">
<dt id="asyncio.Task.result">
<code class="sig-name descname">result</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.Task.result" title="永久链接至目标"></a></dt>
<dd><p>返回 Task 的结果。</p>
<p>如果 Task 对象 <em>已完成</em>,其封包的协程的结果会被返回 (或者当协程引发异常时,该异常会被重新引发。)</p>
<p>如果 Task 对象 <em>被取消</em>,此方法会引发一个 <a class="reference internal" href="asyncio-exceptions.html#asyncio.CancelledError" title="asyncio.CancelledError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">CancelledError</span></code></a> 异常。</p>
<p>如果 Task 对象的结果还不可用,此方法会引发一个 <a class="reference internal" href="asyncio-exceptions.html#asyncio.InvalidStateError" title="asyncio.InvalidStateError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">InvalidStateError</span></code></a> 异常。</p>
</dd></dl>
<dl class="method">
<dt id="asyncio.Task.exception">
<code class="sig-name descname">exception</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.Task.exception" title="永久链接至目标"></a></dt>
<dd><p>返回 Task 对象的异常。</p>
<p>如果所封包的协程引发了一个异常,该异常将被返回。如果所封包的协程正常返回则该方法将返回 <code class="docutils literal notranslate"><span class="pre">None</span></code></p>
<p>如果 Task 对象 <em>被取消</em>,此方法会引发一个 <a class="reference internal" href="asyncio-exceptions.html#asyncio.CancelledError" title="asyncio.CancelledError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">CancelledError</span></code></a> 异常。</p>
<p>如果 Task 对象尚未 <em>完成</em>,此方法将引发一个 <a class="reference internal" href="asyncio-exceptions.html#asyncio.InvalidStateError" title="asyncio.InvalidStateError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">InvalidStateError</span></code></a> 异常。</p>
</dd></dl>
<dl class="method">
<dt id="asyncio.Task.add_done_callback">
<code class="sig-name descname">add_done_callback</code><span class="sig-paren">(</span><em class="sig-param">callback</em>, <em class="sig-param">*</em>, <em class="sig-param">context=None</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.Task.add_done_callback" title="永久链接至目标"></a></dt>
<dd><p>添加一个回调,将在 Task 对象 <em>完成</em> 时被运行。</p>
<p>此方法应该仅在低层级的基于回调的代码中使用。</p>
<p>要了解更多细节请查看 <a class="reference internal" href="asyncio-future.html#asyncio.Future.add_done_callback" title="asyncio.Future.add_done_callback"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Future.add_done_callback()</span></code></a> 的文档。</p>
</dd></dl>
<dl class="method">
<dt id="asyncio.Task.remove_done_callback">
<code class="sig-name descname">remove_done_callback</code><span class="sig-paren">(</span><em class="sig-param">callback</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.Task.remove_done_callback" title="永久链接至目标"></a></dt>
<dd><p>从回调列表中移除 <em>callback</em></p>
<p>此方法应该仅在低层级的基于回调的代码中使用。</p>
<p>要了解更多细节请查看 <a class="reference internal" href="asyncio-future.html#asyncio.Future.remove_done_callback" title="asyncio.Future.remove_done_callback"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Future.remove_done_callback()</span></code></a> 的文档。</p>
</dd></dl>
<dl class="method">
<dt id="asyncio.Task.get_stack">
<code class="sig-name descname">get_stack</code><span class="sig-paren">(</span><em class="sig-param">*</em>, <em class="sig-param">limit=None</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.Task.get_stack" title="永久链接至目标"></a></dt>
<dd><p>返回此 Task 对象的栈框架列表。</p>
<p>如果所封包的协程未完成,这将返回其挂起所在的栈。如果协程已成功完成或被取消,这将返回一个空列表。如果协程被一个异常终止,这将返回回溯框架列表。</p>
<p>框架总是从按从旧到新排序。</p>
<p>每个被挂起的协程只返回一个栈框架。</p>
<p>可选的 <em>limit</em> 参数指定返回框架的数量上限;默认返回所有框架。返回列表的顺序要看是返回一个栈还是一个回溯:栈返回最新的框架,回溯返回最旧的框架。(这与 traceback 模块的行为保持一致。)</p>
</dd></dl>
<dl class="method">
<dt id="asyncio.Task.print_stack">
<code class="sig-name descname">print_stack</code><span class="sig-paren">(</span><em class="sig-param">*</em>, <em class="sig-param">limit=None</em>, <em class="sig-param">file=None</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.Task.print_stack" title="永久链接至目标"></a></dt>
<dd><p>打印此 Task 对象的栈或回溯。</p>
<p>此方法产生的输出类似于 traceback 模块通过 <a class="reference internal" href="#asyncio.Task.get_stack" title="asyncio.Task.get_stack"><code class="xref py py-meth docutils literal notranslate"><span class="pre">get_stack()</span></code></a> 所获取的框架。</p>
<p><em>limit</em> 参数会直接传递给 <a class="reference internal" href="#asyncio.Task.get_stack" title="asyncio.Task.get_stack"><code class="xref py py-meth docutils literal notranslate"><span class="pre">get_stack()</span></code></a></p>
<p><em>file</em> 参数是输出所写入的 I/O 流;默认情况下输出会写入 <a class="reference internal" href="sys.html#sys.stderr" title="sys.stderr"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.stderr</span></code></a></p>
</dd></dl>
<dl class="method">
<dt id="asyncio.Task.get_coro">
<code class="sig-name descname">get_coro</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.Task.get_coro" title="永久链接至目标"></a></dt>
<dd><p>返回由 <a class="reference internal" href="#asyncio.Task" title="asyncio.Task"><code class="xref py py-class docutils literal notranslate"><span class="pre">Task</span></code></a> 包装的协程对象。</p>
<div class="versionadded">
<p><span class="versionmodified added">3.8 新版功能.</span></p>
</div>
</dd></dl>
<dl class="method">
<dt id="asyncio.Task.get_name">
<code class="sig-name descname">get_name</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.Task.get_name" title="永久链接至目标"></a></dt>
<dd><p>返回 Task 的名称。</p>
<p>如果没有一个 Task 名称被显式地赋值,默认的 asyncio Task 实现会在实例化期间生成一个默认名称。</p>
<div class="versionadded">
<p><span class="versionmodified added">3.8 新版功能.</span></p>
</div>
</dd></dl>
<dl class="method">
<dt id="asyncio.Task.set_name">
<code class="sig-name descname">set_name</code><span class="sig-paren">(</span><em class="sig-param">value</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.Task.set_name" title="永久链接至目标"></a></dt>
<dd><p>设置 Task 的名称。</p>
<p><em>value</em> 参数可以为任意对象,它随后会被转换为字符串。</p>
<p>在默认的 Task 实现中,名称将在任务对象的 <a class="reference internal" href="functions.html#repr" title="repr"><code class="xref py py-func docutils literal notranslate"><span class="pre">repr()</span></code></a> 输出中可见。</p>
<div class="versionadded">
<p><span class="versionmodified added">3.8 新版功能.</span></p>
</div>
</dd></dl>
<dl class="method">
<dt id="asyncio.Task.all_tasks">
<em class="property">classmethod </em><code class="sig-name descname">all_tasks</code><span class="sig-paren">(</span><em class="sig-param">loop=None</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.Task.all_tasks" title="永久链接至目标"></a></dt>
<dd><p>返回一个事件循环中所有任务的集合。</p>
<p>默认情况下将返回当前事件循环中所有任务。如果 <em>loop</em><code class="docutils literal notranslate"><span class="pre">None</span></code>,则会使用 <a class="reference internal" href="asyncio-eventloop.html#asyncio.get_event_loop" title="asyncio.get_event_loop"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_event_loop()</span></code></a> 函数来获取当前事件循环。</p>
<div class="deprecated-removed">
<p><span class="versionmodified">Deprecated since version 3.7, will be removed in version 3.9: </span>请不要将此方法作为任务方法来调用。 应当改用 <a class="reference internal" href="#asyncio.all_tasks" title="asyncio.all_tasks"><code class="xref py py-func docutils literal notranslate"><span class="pre">asyncio.all_tasks()</span></code></a> 函数。</p>
</div>
</dd></dl>
<dl class="method">
<dt id="asyncio.Task.current_task">
<em class="property">classmethod </em><code class="sig-name descname">current_task</code><span class="sig-paren">(</span><em class="sig-param">loop=None</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.Task.current_task" title="永久链接至目标"></a></dt>
<dd><p>返回当前运行任务或 <code class="docutils literal notranslate"><span class="pre">None</span></code></p>
<p>如果 <em>loop</em><code class="docutils literal notranslate"><span class="pre">None</span></code>,则会使用 <a class="reference internal" href="asyncio-eventloop.html#asyncio.get_event_loop" title="asyncio.get_event_loop"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_event_loop()</span></code></a> 函数来获取当前事件循环。</p>
<div class="deprecated-removed">
<p><span class="versionmodified">Deprecated since version 3.7, will be removed in version 3.9: </span>请不要将此方法作为任务方法来调用。 应当改用 <a class="reference internal" href="#asyncio.current_task" title="asyncio.current_task"><code class="xref py py-func docutils literal notranslate"><span class="pre">asyncio.current_task()</span></code></a> 函数。</p>
</div>
</dd></dl>
</dd></dl>
</section>
<section id="generator-based-coroutines">
<span id="asyncio-generator-based-coro"></span><h2><a class="toc-backref" href="#id14">基于生成器的协程</a><a class="headerlink" href="#generator-based-coroutines" title="永久链接至标题"></a></h2>
<div class="admonition note">
<p class="admonition-title">注解</p>
<p>对基于生成器的协程的支持 <strong>已弃用</strong> 并计划在 Python 3.10 中移除。</p>
</div>
<p>基于生成器的协程是 async/await 语法的前身。它们是使用 <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code> 语句创建的 Python 生成器,可以等待 Future 和其他协程。</p>
<p>基于生成器的协程应该使用 <a class="reference internal" href="#asyncio.coroutine" title="asyncio.coroutine"><code class="xref py py-func docutils literal notranslate"><span class="pre">&#64;asyncio.coroutine</span></code></a> 装饰,虽然这并非强制。</p>
<dl class="function">
<dt id="asyncio.coroutine">
<code class="sig-prename descclassname">&#64;</code><code class="sig-prename descclassname">asyncio.</code><code class="sig-name descname">coroutine</code><a class="headerlink" href="#asyncio.coroutine" title="永久链接至目标"></a></dt>
<dd><p>用来标记基于生成器的协程的装饰器。</p>
<p>此装饰器使得旧式的基于生成器的协程能与 async/await 代码相兼容:</p>
<div class="highlight-python3 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">old_style_coroutine</span><span class="p">():</span>
<span class="k">yield from</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="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="k">await</span> <span class="n">old_style_coroutine</span><span class="p">()</span>
</pre></div>
</div>
<p>此装饰器不应该被用于 <a class="reference internal" href="../reference/compound_stmts.html#async-def"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code></a> 协程。</p>
<div class="deprecated-removed">
<p><span class="versionmodified">Deprecated since version 3.8, will be removed in version 3.10: </span>请改用 <a class="reference internal" href="../reference/compound_stmts.html#async-def"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code></a></p>
</div>
</dd></dl>
<dl class="function">
<dt id="asyncio.iscoroutine">
<code class="sig-prename descclassname">asyncio.</code><code class="sig-name descname">iscoroutine</code><span class="sig-paren">(</span><em class="sig-param">obj</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.iscoroutine" title="永久链接至目标"></a></dt>
<dd><p>如果 <em>obj</em> 是一个 <a class="reference internal" href="#coroutine"><span class="std std-ref">协程对象</span></a> 则返回 <code class="docutils literal notranslate"><span class="pre">True</span></code></p>
<p>此方法不同于 <a class="reference internal" href="inspect.html#inspect.iscoroutine" title="inspect.iscoroutine"><code class="xref py py-func docutils literal notranslate"><span class="pre">inspect.iscoroutine()</span></code></a> 因为它对基于生成器的协程返回 <code class="docutils literal notranslate"><span class="pre">True</span></code></p>
</dd></dl>
<dl class="function">
<dt id="asyncio.iscoroutinefunction">
<code class="sig-prename descclassname">asyncio.</code><code class="sig-name descname">iscoroutinefunction</code><span class="sig-paren">(</span><em class="sig-param">func</em><span class="sig-paren">)</span><a class="headerlink" href="#asyncio.iscoroutinefunction" title="永久链接至目标"></a></dt>
<dd><p>如果 <em>func</em> 是一个 <a class="reference internal" href="#coroutine"><span class="std std-ref">协程函数</span></a> 则返回 <code class="docutils literal notranslate"><span class="pre">True</span></code></p>
<p>此方法不同于 <a class="reference internal" href="inspect.html#inspect.iscoroutinefunction" title="inspect.iscoroutinefunction"><code class="xref py py-func docutils literal notranslate"><span class="pre">inspect.iscoroutinefunction()</span></code></a> 因为它对以 <a class="reference internal" href="#asyncio.coroutine" title="asyncio.coroutine"><code class="xref py py-func docutils literal notranslate"><span class="pre">&#64;coroutine</span></code></a> 装饰的基于生成器的协程函数返回 <code class="docutils literal notranslate"><span class="pre">True</span></code></p>
</dd></dl>
</section>
</section>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<h3><a href="../contents.html">目录</a></h3>
<ul>
<li><a class="reference internal" href="#">协程与任务</a><ul>
<li><a class="reference internal" href="#coroutines">协程</a></li>
<li><a class="reference internal" href="#awaitables">可等待对象</a></li>
<li><a class="reference internal" href="#running-an-asyncio-program">运行 asyncio 程序</a></li>
<li><a class="reference internal" href="#creating-tasks">创建任务</a></li>
<li><a class="reference internal" href="#sleeping">休眠</a></li>
<li><a class="reference internal" href="#running-tasks-concurrently">并发运行任务</a></li>
<li><a class="reference internal" href="#shielding-from-cancellation">屏蔽取消操作</a></li>
<li><a class="reference internal" href="#timeouts">超时</a></li>
<li><a class="reference internal" href="#waiting-primitives">简单等待</a></li>
<li><a class="reference internal" href="#scheduling-from-other-threads">跨线程调度</a></li>
<li><a class="reference internal" href="#introspection">内省</a></li>
<li><a class="reference internal" href="#task-object">Task 对象</a></li>
<li><a class="reference internal" href="#generator-based-coroutines">基于生成器的协程</a></li>
</ul>
</li>
</ul>
<h4>上一个主题</h4>
<p class="topless"><a href="asyncio.html"
title="上一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">asyncio</span></code> --- 异步 I/O</a></p>
<h4>下一个主题</h4>
<p class="topless"><a href="asyncio-stream.html"
title="下一章"></a></p>
<div role="note" aria-label="source link">
<h3>本页</h3>
<ul class="this-page-menu">
<li><a href="../bugs.html">报告 Bug</a></li>
<li>
<a href="https://github.com/python/cpython/blob/3.8/Doc/library/asyncio-task.rst"
rel="nofollow">显示源代码
</a>
</li>
</ul>
</div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>导航</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="总目录"
>索引</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python 模块索引"
>模块</a> |</li>
<li class="right" >
<a href="asyncio-stream.html" title="流"
>下一页</a> |</li>
<li class="right" >
<a href="asyncio.html" title="asyncio --- 异步 I/O"
>上一页</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.8.20 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python 标准库</a> &#187;</li>
<li class="nav-item nav-item-2"><a href="ipc.html" >网络和进程间通信</a> &#187;</li>
<li class="nav-item nav-item-3"><a href="asyncio.html" ><code class="xref py py-mod docutils literal notranslate"><span class="pre">asyncio</span></code> --- 异步 I/O</a> &#187;</li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="快速搜索" aria-label="快速搜索" type="text" name="q" />
<input type="submit" value="转向" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
|
</li>
</ul>
</div>
<div class="footer">
&copy; <a href="../copyright.html">版权所有</a> 2001-2024, Python Software Foundation.
<br />
This page is licensed under the Python Software Foundation License Version 2.
<br />
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
<br />
<br />
The Python Software Foundation is a non-profit corporation.
<a href="https://www.python.org/psf/donations/">Please donate.</a>
<br />
<br />
最后更新于 12月 09, 2024.
<a href="https://docs.python.org/3/bugs.html">Found a bug</a>?
<br />
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 2.4.4.
</div>
</body>
</html>