1、asyncio
import asyncio
# coroutine function: async开头的函数
async def main():
print('hello')
await asyncio.sleep(1)
print('world')
coro = main() # coroutine object:协程对象
# 当生成协程对象的时候,并不运行函数里面的程序。
# 运行时需要两步走:进入 async 模式、把coroutine变成task
asyncio.run(coro) # 创建 event loop 来跑 task
2、了解 await 作用
import asyncio
import time
async def say_after(delay, what):
await asyncio.sleep(delay)
print(what)
async def main():
print(f"started at {time.strftime('%X')}")
await say_after(1, 'hello') # await 把控制权交还给 event loop
await say_after(2, 'world')
print(f"finished at {time.strftime('%X')}") # 总共花了3秒
coro = main() # coroutine object:协程对象
asyncio.run(coro) # 创建 event loop 来跑 task
3、了解 asyncio.create_task
import asyncio
import time
async def say_after(delay, what):
await asyncio.sleep(delay)
print(what)
async def main():
task1 = asyncio.create_task(say_after(1, 'hello'))
task2 = asyncio.create_task(say_after(2, 'world'))
# create_task 可提前创建好 task
# 到目前为止,两个 task 都已初始化到 event loop 里面了
print(f"started at {time.strftime('%X')}")
await task1
await task2
print(f"finished at {time.strftime('%X')}")
'''
task1 执行1s等待的时候,event loop 是空闲的,
它发现 task2 可以执行,就执行了一秒task2,
所以当 task1 执行完之后,task2 还剩下1秒等待需要执行,所以总体时间花了2秒
async 很适合解决网络通讯的问题,因为网络通讯很多时间是在等待上的,也就是所谓的 io bound task。
等待的时间,可以去完成别的 task
'''
asyncio.run(main())
4、协程返回值怎么获取?
import asyncio
import time
async def say_after(delay, what):
await asyncio.sleep(delay)
return f"{what} - {delay}"
async def main():
task1 = asyncio.create_task(say_after(1, 'hello'))
task2 = asyncio.create_task(say_after(2, 'world'))
print(f"started at {time.strftime('%X')}")
ret1 = await task1 # 拿到返回值
ret2 = await task2
print(ret1)
print(ret2)
print(f"finished at {time.strftime('%X')}")
asyncio.run(main())
5、了解 asyncio.gather
import asyncio
import time
async def say_after(delay, what):
await asyncio.sleep(delay)
return f"{what} - {delay}"
async def main():
task1 = asyncio.create_task(say_after(1, 'hello'))
task2 = asyncio.create_task(say_after(2, 'world'))
print(f"started at {time.strftime('%X')}")
# asyncio.gather的参数可以是若干个协程对象,task,以及asyncio.gather的返回值
# 如果参数是协程对象,它会自动给转化为task
# 最终返回一个list:['hello - 1', 'world - 2']
ret = await asyncio.gather(task1, task2)
print(ret)
print(f"finished at {time.strftime('%X')}")
asyncio.run(main())
6、了解 asyncio.gather 之后优化一下代码
import asyncio
import time
async def say_after(delay, what):
await asyncio.sleep(delay)
return f"{what} - {delay}"
async def main():
print(f"started at {time.strftime('%X')}")
# 直接将协程对象放到 asyncio.gather 中,它会自动变为 task,再逐个 await,
# 最后返回一个列表式的结果:['hello - 1', 'world - 2']
# 协程的意义:同一时间只有一个任务在跑,它只是想办法充分利用中间的等待时间
# 协程对象只有变成了 task 才能被执行,
# 而 await 和 gather 都是隐式地将协程对象变成了 task
ret = await asyncio.gather(
say_after(1, 'hello'),
say_after(2, 'world')
)
print(ret)
print(f"finished at {time.strftime('%X')}")
asyncio.run(main())