Bre*_*eak 3 python task cancellation python-asyncio graceful-shutdown
例子:
with suppress(asyncio.CancelledError):
[await t for t in asyncio.all_tasks(loop=self.loop)
if t is not asyncio.current_task()]
Run Code Online (Sandbox Code Playgroud)
为了避免Task was destroyed but it is pending!警告,我必须在取消后等待任务,但等待它们会导致终端被垃圾邮件发送CancelledError。我知道它被取消了,但我不需要看到它。
使用contextlib.suppress此处会对取消产生负面影响吗?我可以避免看到取消的错误(或任务被破坏的警告而无需等待)的唯一其他方法是使用asyncio.wait而不是启动我的初始任务asyncio.gather。由于某种原因,wait似乎抑制了异常。我用了return_when=asyncio.FIRST_EXCEPTION一个wait又return_exceptions=True一个gather。但似乎无论我如何设置它们的关键字参数,都会打印异常,而不会gather打印异常。wait
CancelledError在 asyncio 中用于两个目的:一是发出取消请求信号- 这是您在被取消的协程中收到的请求 - 另一种是发出取消响应信号- 这是您在等待任务的协程中收到的请求。抑制取消请求是一个坏主意,因为它会使协程不响应取消,从而导致以后出现问题。但是抑制响应是完全可以的,因为您可能希望等待取消的协程(例如,为了避免此警告)而不传播异常。
请注意,您所做的方式看起来不太正确,因为列表理解将在first CancelledError终止,因此您将无法等待其他协程。正确的方法是放入suppress循环内,例如:
for t in tasks:
with contextlib.suppress(asyncio.CancelledError):
await t
# or, simpler:
await asyncio.gather(*tasks, return_exceptions=True)
Run Code Online (Sandbox Code Playgroud)
wait()不会传播异常,因为它返回future集而不是它们的结果。如果您尝试访问返回的 future 的结果,您会遇到异常。gather(return_exceptions=True)返回结果和异常的混合,并且它不应该引发任何内容。如果是,请编辑问题以提供一个最小的示例。