<h3>上下文</h3>
<p>首先,让我们考虑更广泛的背景:</p>
<p><code>caller() > your_coro() > callee()</code></p>
<p>您可以控制协同程序,但不能控制调用者,只能部分控制被调用者。在</p>
<p>默认情况下,“向上传播”和“向下传播”都是有效的:</p>
<pre><code>(1)
caller1() + (2)
+ > callee()
caller2() > your_coro() +
(4) (3)
</code></pre>
<p>在这个图中,语义和<strong>非常松散地</strong>,如果<code>caller1()</code>被主动取消,那么{<cd3>}被取消,然后你的协程被取消,然后{<cd4>}被取消。如果<code>caller2()</code>被主动取消,也会发生大致相同的情况。在</p>
<p>(<code>callee()</code>是共享的,因此不是一个普通的协程,而是<code>Task</code>或<code>Future</code>)</p>
<p>你想要什么样的替代行为?在</p>
<h3>屏蔽</h3>
<p>如果您希望<code>callee()</code>继续,即使<code>caller2()</code>被取消,<code>shield</code>它:</p>
^{pr2}$
<h3>反向屏蔽</h3>
<p>如果您允许<code>callee()</code>死亡,但希望您的协同程序继续,请转换异常</strong>:</p>
<pre class="lang-py prettyprint-override"><code>async def reverse_shield(awaitable):
try:
return await awaitable
except asyncio.CancelledError:
raise Exception("custom")
async def your_coro():
await reverse_shield(callee_f)
# handle custom exception
</code></pre>
<h3>保护自己</h3>
<p>这个问题值得怀疑-通常你应该允许你的来电者取消你的合作计划。在</p>
<p>一个值得注意的例外是,如果你的调用者是一个框架,并且它是不可配置的。在</p>
^{4}$