随着互联网应用的不断发展,高性能和响应速度成为应用程序设计的重要考量因素。异步IO编程是一种实现高性能和响应速度的有效方法。Python 3.4及以上版本引入了一个新的标准库模块asyncio
,用于编写单线程并发的异步网络应用。
1、asyncio模块简介
asyncio
是一个用于编写单线程并发的Python库,它基于async/await
语法。它提供了事件循环、协程、任务、通道等概念,用于实现异步IO操作。
- 事件循环(Event Loop):事件循环是
asyncio
的核心,它负责调度和执行异步任务。 - 协程(Coroutines):协程是
asyncio
中的异步函数,使用async def
定义。协程可以挂起和恢复执行,使得其他协程有机会运行。 - 任务(Tasks):任务是
asyncio
中的一个概念,用于管理协程的执行。任务可以挂起和恢复协程,并跟踪协程的状态。 - 通道(Channels):通道是
asyncio
中的一个概念,用于在协程之间传递数据。通道可以保证数据按照发送和接收的顺序进行传递。
2、创建事件循环
在asyncio
中,首先需要创建一个事件循环。事件循环负责调度和执行异步任务。
以下是一个创建事件循环的示例:
import asyncio
# 创建事件循环
loop = asyncio.get_event_loop()
在这个示例中,我们使用asyncio.get_event_loop()
函数获取当前事件循环。如果事件循环不存在,将创建一个新的事件循环。
3、定义协程
在asyncio
中,协程是使用async def
定义的异步函数。协程可以使用await
表达式挂起执行,直到等待的操作完成。
以下是一个定义协程的示例:
import asyncio
async def hello_world():
print('Hello')
await asyncio.sleep(1)
print('World')
# 运行协程
loop.run_until_complete(hello_world())
在这个示例中,我们定义了一个名为hello_world
的协程,它首先打印"Hello",然后等待1秒,最后打印"World"。我们使用loop.run_until_complete()
方法运行协程,直到协程完成。
4、协程的挂起和恢复
在asyncio
中,协程可以使用await
表达式挂起执行。当协程挂起时,事件循环会将控制权交给其他协程,直到等待的操作完成。
以下是一个使用协程挂起和恢复的示例:
import asyncio
async def wait_for_seconds(seconds):
await asyncio.sleep(seconds)
return 'Done after {} seconds'.format(seconds)
async def main():
print('Starting')
result = await wait_for_seconds(2)
print(result)
print('Finished')
# 运行协程
loop.run_until_complete(main())
在这个示例中,我们定义了一个名为wait_for_seconds
的协程,它使用asyncio.sleep()
方法等待指定的秒数。我们定义了一个名为main
的协程,它首先调用wait_for_seconds
协程,并等待其完成。最后,main
协程打印结果并完成。
5、创建任务
在asyncio
中,任务是用于管理协程执行的实体。任务可以挂起和恢复协程,并跟踪协程的状态。
以下是一个创建任务的示例:
import asyncio
async def say_after(delay, what):
await asyncio.sleep(delay)
print(what)
async def main():
print(f"started at {time.strftime('%X')}")
task1 = asyncio.create_task(say_after(1, 'hello'))
task2 = asyncio.create_task(say_after(2, 'world'))
# 等待任务完成
await task1
await task2
print(f"finished at {time.strftime('%X')}")
# 6、运行协程
loop.run_until_complete(main())
在这个示例中,我们定义了一个名为say_after
的协程,它使用asyncio.sleep()
方法等待指定的秒数,然后打印指定的字符串。我们定义了一个名为main
的协程,它创建了两个任务task1
和task2
,分别调用say_after
协程并等待其完成。最后,main
协程打印结果并完成。
6、通道(Channels)
通道是asyncio
中的一个概念,用于在协程之间传递数据。通道可以保证数据按照发送和接收的顺序进行传递。
以下是一个使用通道的示例:
import asyncio
async def producer(channel):
for i in range(5):
print(f"producer sending {i}")
channel.send(i)
await asyncio.sleep(1)
async def consumer(channel):
while True:
value = await channel.receive()
print(f"consumer received {value}")
async def main():
channel = asyncio.Queue()
producer_task = asyncio.create_task(producer(channel))
consumer_task = asyncio.create_task(consumer(channel))
await producer_task
await consumer_task
# 运行协程
loop.run_until_complete(main())
在这个示例中,我们定义了一个名为producer
的协程,它生成一个数字序列,并将每个数字发送到通道。我们定义了一个名为consumer
的协程,它从通道接收数字,并打印出来。我们定义了一个名为main
的协程,它创建了生产者和消费者任务,并等待它们完成。
7、结论
asyncio
是Python中用于编写单线程并发的异步网络应用的库。它提供了事件循环、协程、任务和通道等概念,用于实现异步IO操作。通过使用async/await
语法,我们可以编写高效的异步代码,提高应用程序的性能和响应速度。