python多线程协程同步异步系列

### Python 协程库中同步异步的使用方法及原理 #### 一、`asyncio` 库简介 `asyncio` 是 Python 自带的一个标准库,自 Python 3.4 开始被引入[^2]。它主要用于编写单线程并发代码,基于协程的概念实现了异步 I/O 操作的支持。 --- #### 二、同步异步的区别 - **同步**:程序按照顺序依次执行每一步操作,在某一时刻只有一个任务在运行。如果某个任务涉及长时间的 I/O 操作(如网络请求),整个程序会被阻塞直到该操作完成。 - **异步**:允许多个任务在同一时间段内交替执行。当某一个任务因 I/O 操作而暂停时,其他任务可以继续运行,从而提高效率[^4]。 --- #### 三、`asyncio` 的核心概念 1. **事件循环 (`Event Loop`)** `asyncio` 提供了一个事件循环机制,负责调度管理所有的异步任务。通过调用 `loop.run_until_complete()` 或者 `asyncio.run()` 来启动事件循环并执行指定的任务集合[^2]。 2. **协程 (`Coroutine`)** 协程是一种特殊的函数,可以通过 `async def` 关键字定义。它们可以在特定位置挂起自身的执行,并让控制权返回给事件循环,以便后者能够安排其他任务的运行[^1]。 3. **Future 对象** 表示尚未完成的操作结果。一旦关联的任务结束,这个对象就会保存最终的结果或者异常状态。 4. **Task 对象** Task 是 Future 的子类,封装了具体的协程实例,便于对其进行跟踪管理优先级设置。 --- #### 四、基本语法结构 以下是构建异步应用程序所需的关键组件及其作用: 1. **定义协程** 使用 `async def` 定义一个协程函数: ```python async def my_coroutine(): ... ``` 2. **等待协程** 利用 `await` 关键词来暂停当前协程直至另一个协程完成其工作流程: ```python result = await another_coroutine() ``` 3. **创建任务** 将协程转换成可由事件循环监控的任务: ```python task = asyncio.create_task(my_coroutine()) ``` 4. **收集任务** 当有多个独立但又相互依赖的任务需要同时被执行时,可以用 `gather` 方法一次性提交这些任务至事件循环: ```python results = await asyncio.gather(*tasks) ``` 5. **运行事件循环** 如果是在脚本顶层,则推荐采用更简洁的方式——即直接调用 `asyncio.run(main())`;而在交互环境中可能还需要手动获取默认的 event loop 并显式地调用相应的方法[^1]。 --- #### 五、实际案例分析 下面展示如何运用上述知识点实现简单的异步爬虫功能[^5]: ```python import asyncio import time urls = ['http://example.com/page1', 'http://example.com/page2', 'http://example.com/page3'] async def fetch_url(url): print(f'Start fetching {url}') # Simulate network delay using sleep. await asyncio.sleep(2) # Replace this line with real HTTP request logic later on. print(f'Finished fetching {url}') async def main(): start_time = time.perf_counter() tasks = [] for url in urls: tasks.append(fetch_url(url)) await asyncio.gather(*tasks) elapsed_time = time.perf_counter() - start_time print(f'Total execution time: {elapsed_time:.2f} seconds') if __name__ == '__main__': asyncio.run(main()) ``` 在此例子当中,我们模拟向三个不同的 URL 发送 GET 请求的过程。由于采用了异步方式处理每一个连接尝试,所以即使存在延迟也不会影响整体性能表现。 --- #### 六、注意事项 尽管现代版本已经淘汰了一些旧式的写法比如 `@asyncio.coroutine` `yield from`[^1],但在阅读早期文档资料的时候仍有可能碰到此类表达形式。因此熟悉两者之间的映射关系也是很有必要的。 另外值得注意的一点就是关于上下文管理器(`with`)以及对应的异步版(`async with`)的应用场景差异[^3]。前者适用于传统的文件读取之类的短平快型事务性作业;而后者的适用范围更加广泛些,尤其适合那些涉及到复杂初始化/销毁逻辑的对象生命周期管控场合之中。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值