一、前言
最近看到很多关于 asyncio
的代码,所以本篇文章,我们需要详细聊一下 asyncio
,不会有过多的关于 asyncio
本身函数使用的例子,重点关注是什么以及为什么,asyncio
函数相对较简单。
二、asyncio
2.1 asyncio 是什么?
- 本质:
asyncio
是基于协程的,提供了一套编写单线程并发代码的框架。它使用async
和await
语法来定义和执行异步操作,从而避免了传统的回调方式,代码更加直观和易于维护。asyncio
往往是构建 IO 密集型和高层级 结构化 网络代码的最佳选择。 - 三条原则:
- 异步性:使用
async
定义异步函数,await
用于挂起阻塞操作,如 IO 请求。 - 事件循环:
asyncio
提供事件循环来管理和调度执行异步任务。 - 协程:异步函数在 Python 中被称为协程,它们是可等待对象,可以在事件循环中被挂起和恢复。
2.2 asyncio 解决了什么问题
- 起源:
asyncio
是 Python 用于解决异步 IO 编程的标准库,它在 Python 3.4 版本中引入。它的出现是为了提供一种简单的方式来编写并发代码。在此之前,Python 通过多线程和多进程等方式实现并发,但这些方式在性能和易用性上存在限制。 - 对比状态:
- 出现之前:Python 开发者需要依赖
threading
或multiprocessing
模块来实现并发,这不仅编程模型复杂,而且在处理大量并发网络连接时效率低下。 - 出现之后:
asyncio
提供了事件循环和协程的概念,使得开发者能够以更低的开销实现大规模 IO 密集型任务的并发。
- 怎么理解?来看一下一个具体的案例:
- 背景:假设有一个需要从多个网站上下载数据的任务。
- 解决方案:使用
asyncio
创建异步函数来发起网络请求,并且并发地等待所有请求完成,而不是顺序地一个接一个地请求,从而大大提高了效率。 - 代码片断:
python
- 复制代码
import asyncio
import aiohttp
async def download_site(session, url):
async with session.get(url) as response:
print(f"Read {response.content_length} from {url}")
async def download_all_sites(sites):
async with aiohttp.ClientSession() as session:
tasks = []
for url in sites:
task = asyncio.create_task(download_site(session, url))
tasks.append(task)
await asyncio.gather(*tasks)
sites = ["https://example1.com", "https://example2.com"]
asyncio.run(download_all_sites(sites))
- 在这个例子中,我们定义了两个异步函数
download_site
和download_all_sites
。download_site
函数用于下载单个网站的内容,而download_all_sites
函数则创建了一个ClientSession
并发起多个异步请求,最后使用asyncio.gather
并发等待所有的请求完成。通过这种方式,我们可以利用 asyncio 实现高效的并发 IO 操作。
在asyncio
出现之前,Python 开发者常用threading
模块来实现并发。以下是一个使用threading
模块下载多个网站内容的例子:
python
- 复制代码
import threading
import requests
from time import time
def download_site(url):
with requests.get(url) as response:
print(f"Read {len(response.content)} from {url}")
def download_all_sites(sites):
threads = []
for url in sites:
thread = threading.Thread(target=download_site, args=(url,))
thread.start()
threads.append(thread)
for thread in threads:
thread.join()
if __name__ == "__main__":
sites = ["https://example1.com", "https://example2.com"] * 10
start_time = time()
download_all_sites(sites)
duration = time() - start_time
print(f"Downloaded {len(sites)} sites in {duration} seconds")
2.23 asyncio 例子
直观的感受一下:
python
复制代码
import asyncio
async def say_hello():
print("Hello,")
await asyncio.sleep(1)
print("World!")
asyncio.run(say_hello())
其他方法的使用,我们就不过多的举例子了,具体可以参考官方文档,相对较简单!
三、总结
本文详细介绍了Python中的asyncio库,包括其本质、解决的问题以及提供的示例。asyncio是基于协程的框架,使用async和await语法来定义和执行异步操作,避免了传统的回调方式,适合构建IO密集型和高层级结构化网络代码。它解决了Python中多线程和多进程方式实现并发时的性能和易用性限制。最后,提供了一个简单的示例来展示asyncio的使用。