asyncio.all_tasks 返回当前事件循环中所有未完成的Task对象集合(set),为空常因未启动事件循环、无活跃循环、任务已完结或跨线程未正确设置循环。
asyncio.all_tasks 返回什么,为什么有时为空
asyncio.all_tasks 返回当前事件循环中所有未完成的 Task 对象集合(set),但它**只作用于当前线程中已运行且未关闭的事件循环**。常见误区是直接调用却返回空集,原因通常是:
- 还没手动启动事件循环(比如没调用
asyncio.run()或loop.run_until_complete()) - 在非协程函数里调用(例如普通同步函数中),此时可能没有活跃的事件循环
- 任务已全部完成或被取消,集合自然为空
- 使用了自定义事件循环但未正确设置为“当前循环”(
asyncio.set_event_loop()未调用)
在 asyncio.run() 内部安全获取任务列表
最稳妥的时机是在事件循环运行中、且至少有一个任务处于 pending 状态时调用。典型做法是在主协程内打印:
import asyncioasync def worker(n): await asyncio.sleep(n) print(f"Worker {n} done")
async def main():
启动多个任务
tasks = [asyncio.create_task(worker(i)) for i in range(3)] print("当前任务数:", len(asyncio.all_tasks())) # 输出类似:当前任务数: 4(含 main 本身 + 3 个 worker) await asyncio.gather(*tasks)asyncio.run(main())
注意:
asyncio.all_tasks()包含main()自身这个任务,不只返回你create_task()出来的那些。跨线程或子循环中调用失败怎么办
如果你在新线程里手动创建了
asyncio.new_event_loop(),必须显式设置并启用它:
- 调用
loop.set_event_loop(loop)(或asyncio.set_event_loop(loop)) - 确保在该线程内调用
asyncio.all_tasks(),而不是主线程 - 不能在
asyncio.run()启动的隐式循环外直接调用——它会抛出RuntimeError: no running event loop
错误示例:asyncio.all_tasks() 在线程函数开头就调用,但 loop.run_forever() 还没开始;正确做法是放进 loop.create_task() 的协程里再查。
all_tasks() 和 current_task() 的关键区别
asyncio.current_task() 只返回当前正在执行的那个 Task 对象(协程上下文中的自身),而 asyncio.all_tasks() 返回全部。它们用途完全不同:
- 调试时想看“我这个任务是谁”,用
current_task() - 想统计或遍历所有活跃任务(比如做清理、监控、超时管理),才用
all_tasks() -
all_tasks()返回的是set,不是按启动顺序排列,也不能保证包含刚create_task()但尚未调度的任务(取决于调度器状态)
真正容易被忽略的一点:任务对象一旦完成(done 或 cancelled),就会从 all_tasks() 集合中自动移除——这不是延迟问题,是设计如此。别指望靠轮询它来“等待任务结束”。