先上代码:
import asyncio
async def test():
print('one')
await asyncio.sleep(1)
print('two')
async def main():
a=asyncio.create_task(test())
b=asyncio.create_task(test())
c=asyncio.create_task(test())
print('hello')
await a,b,c
asyncio.run(main())
运行结果很完美:
hello
one
one
one
two
two
two
修改代码,删除await a,b,c
import asyncio
async def test():
print('one')
await asyncio.sleep(1)
print('two')
async def main():
a=asyncio.create_task(test())
b=asyncio.create_task(test())
c=asyncio.create_task(test())
print('hello')
asyncio.run(main())
hello
one
one
one
Process finished with exit code 0
可以发现test()执行了,但是没有'two'。再次修改代码增加
import asyncio
async def test():
print('one')
await asyncio.sleep(1)
print('two')
async def main():
a=asyncio.create_task(test())
b=asyncio.create_task(test())
c=asyncio.create_task(test())
print('hello')
await asyncio.sleep(1)
asyncio.run(main())
结果为:
hello
one
one
one
two
two
two
实际执行过程为:
1、asyncio.run(main()),程序进入 main() 函数,事件循环开启;
2、任务a、b、c被创建,并进入事件循环等待运行;运行到 print时,输出 'hello';
3、如果运行到await,则从当前的主任务中切出,事件调度器开始调度 a
4、在a中打印'one',运行到 await asyncio.sleep(1),从当前任务切出,事件调度器开始调度 b
5、在b中打印'one',运行到 await asyncio.sleep(1),从当前任务切出,事件调度器开始调度 c
6、在c中打印'one',运行到 await asyncio.sleep(1),从当前任务切出。
7、如果后续程序,如第二段代码中没有await,主程序认为程序运行完毕,则结束进程,不会打印'two'。
8、如果await a,b,c 则主程序会等待a、b、c执行完毕。
9、如果main函数中没有await a,b,c,而是await asyncio.sleep(1),则a、b、c依旧有时间执行完程序,所以会输出'two',但如果await asyncio.sleep(0.5)则a、b、c在执行完毕前程序就会被杀死,所以依旧不会输出'two'。
如果我们想给某些协程任务限定运行时间,一旦超时就取消,或者协程运行错误应该怎么处理呢?这里贴上某位大佬的代码:
import asyncio
async def worker_1():
await asyncio.sleep(1)
return 1
async def worker_2():
await asyncio.sleep(2)
return 2 / 0
async def worker_3():
await asyncio.sleep(3)
return 3
async def main():
task_1 = asyncio.create_task(worker_1())
task_2 = asyncio.create_task(worker_2())
task_3 = asyncio.create_task(worker_3())
await asyncio.sleep(2)
task_3.cancel()
res = await asyncio.gather(task_1, task_2, task_3, return_exceptions=True)
print(res)
%time asyncio.run(main())
########## 输出 ##########
[1, ZeroDivisionError('division by zero'), CancelledError()]
Wall time: 2 s