Python 取消执行中的 asyncio Task `run_until_complete`、`run_forever`、Task
·
如何取消执行中的task
"""
1、run_until_complete和run_ forever
2.取消task
"""
import asyncio
loop = asyncio.get_event_loop()
loop.run_until_complete()
loop.run_forever()
# task ->loop
# loop ->task
一、核心知识点
1. run_until_complete vs run_forever
loop.run_until_complete(future_or_task)- 启动事件循环,直到指定的 Future/Task 完成后停止。
- 常用于一次性任务(如主协程)。
loop.run_forever()- 启动事件循环,让其一直运行,直到手动调用
loop.stop()。 - 适合需要长期运行的服务(如服务器)。
- 启动事件循环,让其一直运行,直到手动调用
2. 取消 Task
- Task 对象有
cancel()方法,可以请求取消正在执行的协程。 - 被取消的协程会在下一个可等待点(
await)抛出asyncio.CancelledError异常。 - 你可以在协程内部捕获这个异常,做清理或善后处理。
二、完整代码示例与解释
示例:如何取消一个正在执行的 Task
import asyncio
async def long_task():
print('Task started')
try:
await asyncio.sleep(10) # 模拟长时间任务
except asyncio.CancelledError:
print('Task was cancelled!')
raise
print('Task finished')
async def main():
# 创建任务
task = asyncio.create_task(long_task())
await asyncio.sleep(2) # 让任务先运行2秒
print('Now cancel the task...')
task.cancel() # 请求取消任务
try:
await task # 等待任务被取消并处理异常
except asyncio.CancelledError:
print('main: Task cancellation confirmed.')
# 用 run_until_complete 执行 main 协程
asyncio.run(main())
逐行解释
-
定义长任务协程
async def long_task(): print('Task started') try: await asyncio.sleep(10) # 模拟长时间任务 except asyncio.CancelledError: print('Task was cancelled!') raise print('Task finished')long_task是一个协程,开始时打印“Task started”。await asyncio.sleep(10)模拟一个耗时10秒的操作。- 如果在 sleep 期间被取消,会抛出
asyncio.CancelledError,被 except 捕获,打印“Task was cancelled!”。
-
定义主协程
async def main(): task = asyncio.create_task(long_task()) await asyncio.sleep(2) # 让任务先运行2秒 print('Now cancel the task...') task.cancel() # 请求取消任务 try: await task # 等待任务被取消并处理异常 except asyncio.CancelledError: print('main: Task cancellation confirmed.')- 创建并调度
long_task,返回 Task 对象。 - 主协程先等待2秒(让 long_task 运行一会儿)。
- 调用
task.cancel()请求取消任务。 await task等待任务结束(此时会抛出 CancelledError)。- 捕获异常,确认任务已被取消。
- 创建并调度
-
启动事件循环
asyncio.run(main())- 启动事件循环,执行
main()协程,直到其完成。
- 启动事件循环,执行
输出示例
Task started
Now cancel the task...
Task was cancelled!
main: Task cancellation confirmed.
三、Task 与 Loop 的关系
- Task -> Loop:每个 Task 都属于一个事件循环(loop),由 loop 调度执行。
- Loop -> Task:事件循环可以管理、调度、取消所有注册的 Task。
四、总结
- 用
task.cancel()可以请求取消正在执行的协程任务。 - 被取消的协程会在下一个
await处抛出asyncio.CancelledError,可用于清理和善后。 run_until_complete适合一次性任务,run_forever适合长期运行服务。- Task 和事件循环是相互关联的,Task 由 Loop 调度,Loop 可以取消 Task。
更多推荐


所有评论(0)