Python 现代开发学习笔记

(七)协程对象与 await

1. 调用异步函数还没有执行函数体

async def 定义异步函数,调用后得到协程对象。先看它何时真正开始:

# 项目文件:demos/coroutine_start.py
# 先建立协程对象,再用 await 推进它;sleep(0) 让出一次执行机会。
import asyncio


async def read_title(trace):
    trace.append("进入函数")
    await asyncio.sleep(0)
    trace.append("等待后恢复")
    return "Python"


async def main():
    trace = []
    operation = read_title(trace)
    print(type(operation).__name__, trace)
    title = await operation
    print(title, trace)


if __name__ == "__main__":
    asyncio.run(main())

先输出 coroutine [],再输出 Python ['进入函数', '等待后恢复']。普通函数调用时立刻进入函数体,协程调用先交回一个等待执行的对象;这里的 await 才继续推进它。

asyncio.run(main()) 为脚本建立并管理事件循环,运行入口协程,退出时收尾。已经运行事件循环的交互环境可以直接 await main(),不再在其中嵌套一次 run。

2. 等待的对象与当前任务

await 接收可等待对象,例如协程、Task 与异步库交回的等待结果。它会取得这个操作的结果,也会传播操作中的异常。遇到尚未完成的异步等待时,当前任务可以暂停,循环转而推进其他准备好的工作。

一个异步函数可以在没有等待的情况下直接返回;await 这样的函数不一定暂停。把耗时循环包成 async def,再写一次 await,也不会自动把这段计算变成后台并行工作。

协程调用先得到对象,await后进入函数,在等待处暂停并恢复返回值

笔记正文与全部题解 · Ctrl / ⌘ K