文章目录
1 一些概念
1.1 协程
执行实体每次执行一个执行流/任务,当前执行流/任务遇阻塞,执行实体切换到其他执行流/任务。执行实体在多个执行流/任务中切换,形成一种并发机制,每个执行流/任务就是一个协程。
1.2 事件循环
直接调用协程返回一个协程对象,并不真正执行协程。协程要在事件循环中被调度执行。事件循环管理协程执行流,当协程阻塞,事件循环将调度其他未阻塞的协程继续执行。
async.run(coro)将启动事件循环并运行主协程coro。await将停止一个阻塞的协程恢复另一个不阻塞的协程。
2 coroutine in Python
2.1 协程的执行
await coro1()暂停当前协程,切换到协程coro1执行,直到coro1()执行完毕,才恢复main_coro()执行。而对于coro1(),执行到await asyncio.sleep(3),停止执行coro1(),切换执行asyncio.sleep(3)。asyncio.sleep(3)执行耗时3s后,恢复执行coro1(),coro1()执行完毕后切换main_coro执行。这就是切换协程的顺序性。
2.1.1 例子1
import asyncio
import time
async def coro1(x):
print('coro1 starts!')
await asyncio.sleep(3)
print('coro1 ends!')
return x
async def main_coro():
print('main_coro starts!')
ret = await coro1(1)
print('main_coro1 ends! coro1 return: %d' % ret)
if __name__ == '__main__':
start_time = time.time()
asyncio.run(main_coro())
end_time = time.time()
print('total cost: %fs' % (end_time - start_time))
'''输出
main_coro starts!
coro1 starts!
coro1 ends!
main_coro1 ends! coro1 return: 1
total cost: 3.002261s
'''
2.1.2 例子2
可以看出这种串行调度并没利用好协程并发处理的优势。可以引入task来应对。
import asyncio
import time
async def fetch_data(data_id: int) -> None:
print(f'Fetching data for ID {
data_id}'