最先接触到异步的,应该是前端,比如 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
# 调用异步函数
协程
可用来表示两个紧密关联的概念:
- 协程函数: 定义形式为
async def
的函数;- 协程对象: 调用
协程函数
所返回的对象。
由上可见,调用异步函数(或者说,协程函数)并不是执行函数,而是生成了一个协程对象。
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
。