给定一个和每个任务组文档中taskgroup
正在运行的任务数,如果任何任务出现错误,则组中的其余任务将被取消。
如果其中一些任务在取消时需要执行清理,那么如何在任务中检测被取消的任务?
希望在任务中引发一些异常,但事实并非如此:
脚本.py:
import asyncio
class TerminateTaskGroup(Exception):
"""Exception raised to terminate a task group."""
async def task_that_needs_to_cleanup_on_cancellation():
try:
await asyncio.sleep(10)
except Exception:
print('exception caught, performing cleanup...')
async def err_producing_task():
await asyncio.sleep(1)
raise TerminateTaskGroup()
async def main():
try:
async with asyncio.TaskGroup() as tg:
tg.create_task(task_that_needs_to_cleanup_on_cancellation())
tg.create_task(err_producing_task())
except* TerminateTaskGroup:
print('main() termination handled')
asyncio.run(main())
执行后,我们可以看到没有引发任何异常task_that_needs_to_cleanup_on_cancellation()
:
$ python3 script.py
main() termination handled
随意地,我可能会避免以这种方式故意取消任务组的设计
但是,你可以除外
asyncio.CancelledError
或使用finally
块为了避免这种取消期间的清理,你可以将潜在的清理工作打包到一个集合中,以便调用者在其异常处理程序中或稍后处理
这两种设计都感觉有点丑陋,而且也非常具体到个别清理案例,因为我相信异常可能发生在
await
其中的任何请注意,文档还提到
CancelledError
应该重新提出,但如果没有进一步的逻辑,这可能并不重要!此外,
asyncio
在 Python 3.7 中添加了 when ,asyncio.CancelledError
继承自Exception
- 这在 3.8 中更改为BaseException
(并且在所有后续版本中都是如此)https://docs.python.org/3/library/asyncio-exceptions.html