最先接触到异步的,应该是前端,比如 JavaScript,连 Sleep 和 XMLHttpRequest 都是用异步的 Promise 写的。

而这次我正在做的 Web 后端也得用到异步,因为这个后端用到了 Onedrive REST API,每次向 Onedrive 请求需要约 1s,如果不使用异步,这个线程就会卡 1s。如果出现高并发(如图片请求),延时也会成倍的增加。

关于协程,还是推荐看 协程和任务 - Python 3.9.5 文档 (opens new window),了解其原理。至于下面的东西,只是一些语法糖的记录。

# 异步和同步

从语法上,同步函数和异步函数的区别只是一个 async

from time import sleep

def sync_double(x):
    sleep(1)
    return x*2

async def async_double(x):
    sleep(1)
    return x*2

# 调用异步函数

协程 可用来表示两个紧密关联的概念:

  1. 协程函数: 定义形式为 async def 的函数;
  2. 协程对象: 调用 协程函数 所返回的对象。

由上可见,调用异步函数(或者说,协程函数)并不是执行函数,而是生成了一个协程对象。

coro = async_double(3)

coro
# <coroutine object async_double at 0x000002779EC830C0>

在同步函数中调用异步函数,使用 asyncio.run()

import asyncio
result = asyncio.run(async_double(3))
# result = 6

在异步函数中调用异步函数并等待其执行完成(就像是同步函数一样),使用 await

result = await async_double(3)
# result = 6

请注意,同步函数是不能使用 await 关键字的,不然会报 SyntaxError