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

Python中协程异步IO(asyncio)理解与入门_gather

 

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())

Python中协程异步IO(asyncio)理解与入门_协程异步IO_02

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())