问题描述
示例:
with suppress(asyncio.CancelledError):
[await t for t in asyncio.all_tasks(loop=self.loop)
if t is not asyncio.current_task()]
为了避免 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 中用于两个目的:一个是发出取消信号 request - 这是你在协程中被取消的那个 - 另一个是发出取消信号响应 - 这是您在等待任务的协程中得到的响应。抑制取消请求是一个坏主意,因为它会使协程不响应取消,从而导致以后出现问题。但是抑制响应完全没问题,因为您可能希望等待取消的协程(例如避免此警告)而不传播异常。
请注意,您的做法看起来不太正确,因为列表解析将在 first CancelledError
处终止,因此您无需等待其他协程。正确的方法是将 suppress
放入循环中,例如:
for t in tasks:
with contextlib.suppress(asyncio.CancelledError):
await t
# or,simpler:
await asyncio.gather(*tasks,return_exceptions=True)
wait()
不会传播异常,因为它返回 期货 的集合而不是它们的结果。如果您尝试访问返回的期货的结果,则会收到异常。 gather(return_exceptions=True)
返回结果和异常的混合,它不应该引发任何事情。如果是,请编辑问题以提供最小示例。