asyncio 是Python 3.5及更高版本中的一个库,它提供了一种写并发代码的方法,使用 async/await 语法。这使得编写并发代码变得更加简单和直观。本文将深入探讨如何使用 asyncio,从基础到高级。
1. 为什么选择 asyncio?
在开始之前,我们先了解一下为什么要使用 asyncio:
- 性能优化:异步编程允许我们同时执行多个操作,从而提高程序的总体效率。
- 简洁的语法:与传统的线程和进程相比,
async/await语法更加简洁和易于理解。
2. 入门
2.1 什么是 async 和 await?
async定义一个异步函数,该函数返回一个可等待对象。await用于等待一个异步操作完成。
import asyncio
async def hello_world():
print("Hello")
await asyncio.sleep(1)
print("World")
asyncio.run(hello_world())
2.2 事件循环
事件循环是 asyncio 的核心。它可以注册、取消和执行任务。
loop = asyncio.get_event_loop()
loop.run_until_complete(hello_world())
3. 进阶
3.1 任务
任务是用于并发执行的 asyncio 的基本单位。
task = asyncio.create_task(hello_world())
3.2 期望
期望是一种特殊的对象,表示一个将在未来完成的计算。
future = loop.create_future()
3.3 异步迭代器和异步生成器
这两者都是 asyncio 的高级功能,允许异步迭代和生成。
async def async_gen():
for i in range(5):
await asyncio.sleep(1)
yield i
async for i in async_gen():
print(i)
4. 真实世界的例子
4.1 异步网络请求
对于异步的网络请求,我们通常使用 aiohttp 库。首先,您需要安装这个库:
pip install aiohttp
以下是一个简单的异步获取网页内容的例子:
import aiohttp
import asyncio
async def fetch_url(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
async def main():
content = await fetch_url("https://www.example.com")
print(content)
asyncio.run(main())
4.2 异步文件I/O
尽管Python的内置文件操作不是异步的,但我们可以使用 aiofiles 库来异步地读写文件。首先,您需要安装这个库:
pip install aiofiles
以下是异步读取文件的一个例子:
import aiofiles
import asyncio
async def read_file(filename):
async with aiofiles.open(filename, mode='r') as file:
return await file.read()
async def main():
content = await read_file("example.txt")
print(content)
asyncio.run(main())
4.3 协程间通信
asyncio 提供了 Queue 作为协程间的通信机制。以下是一个简单的生产者消费者模型的例子:
import asyncio
async def producer(queue):
for i in range(5):
await asyncio.sleep(1)
await queue.put(i)
print(f"Produced {i}")
async def consumer(queue):
for _ in range(5):
item = await queue.get()
print(f"Consumed {item}")
async def main():
queue = asyncio.Queue()
prod_task = asyncio.create_task(producer(queue))
cons_task = asyncio.create_task(consumer(queue))
await asyncio.gather(prod_task, cons_task)
asyncio.run(main())
5. asyncio 常用方法和功能
-
asyncio.run(coro)- 说明:作为
asyncio程序的主入口点,用于执行一个协程。 - 示例:
asyncio.run(main())
- 说明:作为
-
asyncio.create_task(coro)- 说明:并发地运行协程作为 asyncio 任务。
- 示例:
task = asyncio.create_task(my_coroutine())
-
asyncio.sleep(delay)- 说明:返回一个表示指定延迟的异步可等待对象。
- 示例:
await asyncio.sleep(1)
-
asyncio.gather(*coros)- 说明:并发地运行所有给定的协程或者异步任务。
- 示例:
await asyncio.gather(task1(), task2(), task3())
-
asyncio.Queue()- 说明:提供了一个异步的先入先出队列。常用于协程之间的通信和同步。
- 示例:
queue = asyncio.Queue()
-
asyncio.wait_for(coro, timeout)- 说明:等待协程完成,但有最大超时时间。
- 示例:
await asyncio.wait_for(my_coroutine(), timeout=2)
-
asyncio.wait(tasks, return_when=ALL_COMPLETED)- 说明:等待给定的异步任务或协程完成。
return_when参数可以指定何时返回。 - 示例:
await asyncio.wait([task1, task2], return_when=asyncio.FIRST_COMPLETED)
- 说明:等待给定的异步任务或协程完成。
-
asyncio.Lock()- 说明:异步实现的互斥锁。
- 示例:
lock = asyncio.Lock() async with lock: # critical section of code
-
asyncio.Event()- 说明:提供了一个简单的异步事件系统。
- 示例:
event = asyncio.Event() await event.wait() event.set()
-
asyncio.Semaphore(value=1)
- 说明:提供了一个异步的信号量。
- 示例:
sem = asyncio.Semaphore(10) async with sem: # section of code that uses the resource
asyncio.Future()
- 说明:代表一个异步操作的最终结果。通常不需要手动创建,任务(Task)是它的子类,更常用于实际应用。
- 示例:
future = asyncio.Future()
loop.call_later(delay, callback, *args)
- 说明:在给定的
delay秒数后,执行指定的回调。 - 示例:
loop.call_later(5, print, "Hello after 5 seconds")
6. 总结
asyncio 提供了一种高效、简洁的方式来编写并发代码。通过掌握其基础和高级功能,您可以充分利用Python的异步能力,为您的应用带来更好的性能。