python asyncio 和await
时间: 2025-01-07 16:08:56 浏览: 7
### Python 中 `asyncio` 库及 `await` 关键字使用教程
#### 一、基础概念介绍
在 Python 的异步编程模型中,`asyncio` 是核心库之一。它提供了编写单线程并发代码所需的工具,基于协程、事件循环、任务和其他原语。
- **协程 (Coroutine)**:由带有 `async def` 声明的函数定义而成的对象。当调用这样的函数时,并不会立即执行其中的内容而是返回一个可以被挂起和恢复运行状态的特殊对象——即协程对象[^3]。
- **事件循环 (Event Loop)**:程序启动后进入的一个无限循环过程,在此期间不断监听并处理各种 I/O 或定时器触发的任务。所有的异步操作都依赖于这个中心化的调度机制来协调各个独立工作的单元之间的协作关系[^1]。
- **Task**:为了更好地管理和跟踪多个正在运行中的协程实例的状态变化情况而引入的概念;可以通过 `asyncio.create_task()` 方法显式地将某个普通的协程封装成具有更高优先级级别的 Task 实体以便更高效地参与竞争资源分配权衡考量之中。
- **Future**:表示尚未完成的工作的结果。它可以用来桥接同步世界与异步世界的鸿沟,允许我们以一种统一的方式处理来自不同源头的数据流或计算结果。不过这部分内容暂时还未完全展开说明。
#### 二、`await` 关键字详解
`await` 主要用于等待另一个可等待对象(如上述提到过的三种类型)结束其工作流程后再继续向下执行后续逻辑分支。需要注意的是只有处于异步上下文中才能合法地运用该语法结构:
```python
import asyncio
async def fetch_data(url):
# 模拟网络请求,这里使用 asyncio.sleep 替代实际 IO 操作
await asyncio.sleep(1) # 此处会暂停当前协程直到睡眠时间到达为止
return f"Data from {url}"
```
这段代码展示了最简单的形式下如何利用 `await` 来实现非阻塞式的延时效果模拟真实场景下的数据获取行为[^2]。
对于包含多条连续性的 `await` 表达式的场合,则遵循先进先出原则逐个解决每一个待办事项之后才会推进至下一步动作:
```python
async def main():
data1 = await fetch_data("https://api.example.com/data1") # 首次遇到 await ,整个方法会被挂起直至左侧表达式求值完毕
print(data1)
data2 = await fetch_data("https://api.example.com/data2") # 类似地再次遭遇第二个 await 节点...
print(data2)
if __name__ == "__main__":
asyncio.run(main())
```
然而这种串行化的设计模式显然不是最优解方案,特别是在面对大量相似性质的小型子任务集合时效率低下难以满足高性能需求的应用环境要求。因此官方推荐采用批量提交策略并通过诸如 `asyncio.gather()` 函数一次性收集所有预期产出项从而达到提高吞吐量的目的:
```python
async def parallel_fetches():
urls = ["https://api.example.com/data{}".format(i) for i in range(1, 4)]
tasks = [fetch_data(url) for url in urls]
results = await asyncio.gather(*tasks) # 并发执行多个异步操作并将最终得到的所有响应打包在一起返回给调用者
for result in results:
print(result)
if __name__ == "__main__":
asyncio.run(parallel_fetches())
```
此外还有其他一些高级特性比如超时控制(`wait_for`)、条件判断(`as_completed`)等可以帮助开发者更加灵活自如地掌控复杂的业务逻辑流转路径。
阅读全文