
在Python的异步编程生态中,asyncio无疑是最核心的基础设施,它不仅为协程(Coroutine)、事件循环(Event Loop)、任务(Task)等异步核心概念提供了官方实现,还搭建起了一套完整的异步IO调度框架,让开发者可以用同步代码的书写风格实现高并发的IO密集型任务处理。很多人初识asyncio时总会被它“看起来像同步,实际是异步”的特性迷惑,甚至误以为只要加上async/await关键字就能让程序自动变快,却忽略了异步编程的本质是让事件循环在IO等待的间隙自动切换任务,从而最大化CPU利用率,真正的性能提升只在存在大量IO等待的场景下才能体现出来。

要真正掌握asyncio的使用,先从最基础的协程定义与运行开始理解最为合适。在Python中,只要在函数定义前加上async关键字,这个函数就会变成一个协程函数,直接调用它不会执行函数体内的代码,而是返回一个协程对象,必须交由事件循环调度才能运行。比如我们可以定义一个简单的异步函数,用asyncio.sleep模拟IO等待,再通过事件循环运行它:
```python
import asyncio
async def say_after(delay, content):
await asyncio.sleep(delay)
print(content)
async def main():
print("开始执行主协程")
await say_after(1, "第一秒输出的内容")
await say_after(2, "第二秒输出的内容")
print("主协程执行结束")
asyncio.run(main())
```
这段代码的总执行时间大约是3秒,因为两个say_after是顺序await的,前一个执行完后一个才会开始,这和同步代码的执行逻辑没有区别,很多初学者到这里会觉得asyncio并没有什么用,其实是因为还没有用到任务(Task)的概念。
asyncio中的Task是对协程的封装,它会把协程提交给事件循环,让事件循环在后续的调度中自动执行它,相当于把协程变成了一个“后台运行”的异步任务。如果我们把上面的代码改造成用Task来包裹两个say_after协程,执行效率就会完全不同:
```python
async def main():
print("开始执行主协程")
task1 = asyncio.create_task(say_after(1, "第一秒输出的内容"))
task2 = asyncio.create_task(say_after(2, "第二秒输出的内容"))
await task1
await task2
print("主协程执行结束")
```
这时候程序的总执行时间大约只有2秒,因为两个任务是并发运行的,事件循环在task1等待sleep的间隙会切换到task2执行,两个任务的等待时间重叠在了一起,这就是asyncio并发能力的核心体现。在实际开发中,我们常常会用asyncio.create_task批量创建多个任务,再用asyncio.gather统一等待所有任务完成,gather不仅可以收集所有任务的返回值,还支持设置return_exceptions参数来处理任务异常,避免单个任务失败导致整个并发组崩溃。
除了基础的任务并发,asyncio还提供了很多实用的高级API,用来处理更复杂的异步场景。比如asyncio.wait可以同时等待多个任务,并且支持按完成条件返回,比如FIRST_COMPLETED(第一个任务完成就返回)、FIRST_EXCEPTION(第一个任务抛出异常就返回)、ALL_COMPLETED(所有任务完成才返回),这在需要实现“超时放弃”或者“竞速查询”的场景下非常有用。举个例子,我们要同时向三个不同的接口请求同一个数据,哪个接口先返回就用哪个的结果,剩下的请求直接取消,就可以用asyncio.wait配合FIRST_COMPLETED来实现:
```python
async def fetch_from_api(api_url, delay):
await asyncio.sleep(delay)
return f"来自{api_url}的结果"
async def main():
tasks = [
asyncio.create_task(fetch_from_api("api1.com", 2)),
asyncio.create_task(fetch_from_api("api2.com", 1)),
asyncio.create_task(fetch_from_api("api3.com", 3)),
]
done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
for task in pending:
task.cancel()
for task in done:
print("最快的结果:", task.result())
asyncio.run(main())
```
这段代码只会运行大约1秒,就会拿到api2.com的结果,剩下的两个任务会被主动取消,不会继续占用资源,这种模式在微服务架构的降级策略中经常会用到。
另一个非常实用的asyncio功能是异步上下文管理器和异步迭代器,它们分别对应async with和async for语法,让资源的异步获取与释放、数据的异步遍历变得和同步代码一样简洁。比如常用的异步HTTP客户端aiohttp,就是通过异步上下文管理器来管理客户端会话和请求的,我们可以用它来实现批量并发爬取网页的功能:
```python
import aiohttp
async def fetch_page(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
urls = [
"https://www.example.com",
"https://www.python.org",
"https://www.github.com",
]
async with aiohttp.ClientSession() as session:
tasks = [asyncio.create_task(fetch_page(session, url)) for url in urls]
results = await asyncio.gather(*tasks)
for url, html in zip(urls, results):
print(f"{url} 页面长度:{len(html)}")
asyncio.run(main())
```
在这个例子中
本文由作者笔名:优维 于 2026-09-20 05:15:01发表在本站,原创文章,禁止转载,文章内容仅供娱乐参考,不能盲信。
本文链接: http://www.nxvc.vip/wen/5703.html