Python 的 async/await 语法是 Python 3.5 版本中引入的,旨在简化异步编程模型,特别是与基于回调的异步编程模式相比。async关键字用于定义协程(coroutine)、await 用于等待协程的完成。
协程(Coroutine)
协程是一个能够暂停执行并在将来某个点继续执行的函数。在 Python 中,协程是通过 async def
语句定义的特殊函数。这些函数返回一个协程对象,该对象可以被 await
表达式等待。
async def
async def
用于定义一个异步函数(也称为协程函数)。这个函数内部可以使用 await
关键字来等待其他协程的完成。
await
await
关键字用于等待一个协程的完成。它只能在 async def
定义的异步函数内部使用。当执行到 await
表达式时,当前协程会暂停执行,直到被 await
的协程完成。然后,当前协程会从暂停的地方继续执行,并获取 await
表达式的结果(如果有的话)。
示例
下面是一个简单的示例,展示了如何使用 async/await
语法:
import asyncio
async def fetch_data():
print("Start fetching")
await asyncio.sleep(2) # 模拟IO操作
print("Done fetching")
return {'data': 1}
async def main():
print("Before fetching")
result = await fetch_data()
print("Result:", result)
print("After fetching")
# 运行主函数
asyncio.run(main())
1、fetch_data()中,asyncio.sleep(2)
模拟了一个异步IO操作,await
关键字使得协程在这里暂停执行,等待sleep
函数完成,这期间控制权返回给事件循环,可以处理其它任务。
2、main()中,await fetch_data()等待fetch_data()函数完成。
3、asyncio.run(main())
用来运行最顶层的协程,启动事件循环。
启动多个协程并发的示例
import asyncio
# 定义一个异步函数
async def fetch_data(url):
print(f"开始获取 {url} 的数据...")
# 模拟网络请求,这里用 asyncio.sleep 代替
await asyncio.sleep(1)
return f"{url} 的数据已获取"
# 另一个异步函数,它使用 fetch_data
async def main():
urls = ["https://example.com/1", "https://example.com/2"]
tasks = [fetch_data(url) for url in urls] # 创建协程对象列表
# 使用 asyncio.gather 并发运行协程并等待它们完成
results = await asyncio.gather(*tasks)
for result in results:
print(result)
# 运行异步主函数
asyncio.run(main())
在这个示例中,fetch_data 是一个异步函数,它模拟了从网络获取数据的过程。main 函数创建了多个 fetch_data 协程的实例,并使用 asyncio.gather 并发地运行它们。await asyncio.gather(*tasks) 会等待所有任务完成,并返回它们的结果。
总结
async
和await
只能在支持异步上下文的函数中使用。- 异步函数通常与事件循环一起使用,但 Python 的
asyncio
库会自动处理这些细节,特别是在使用asyncio.run()
函数时。 - 异步编程非常适合处理 I/O 密集型任务,如网络请求、文件读写和数据库操作,因为它允许在等待这些操作完成时释放 CPU。
- 异步编程可能会使代码更难理解和调试,特别是当涉及到复杂的异步逻辑和并发控制时。因此,在决定使用异步编程时,请仔细权衡其优缺点。