Python async模块使用方法杂谈
Python async(协程)是近年来非常流行的一种异步编程模式。async通过事件循环机制和协程技术实现其非阻塞的异步效果,让我们能够更方便、高效地编写异步代码。在本文中,我们将详细讲解Python async模块的使用方法,并带有两个示例说明。
1.异步编程概述
在传统的编程模式中,当程序执行到一个耗时的I/O操作后,程序会一直阻塞在这个操作上,直到I/O操作完成并返回结果。而在异步编程模式中,当程序执行到IO操作时,它不会被一直阻塞,而是可以去处理其他事情,避免了阻塞时间导致的不必要等待。
异步编程是在事件循环(Eventloop)的基础上完成的,协程(Coroutine)则是实现异步编程的核心技术。事件循环相当于一个消息处理器,从消息队列中取出消息,并将确定是能够立即处理的消息传递给对应的协程进行处理。
2.asyncio模块
Python3.4版本后,官方提供的异步编程模块就是asyncio(前身是tulip)。asyncio提供了事件循环机制,并且asyncio也提供了协程的支持,支持异步I/O和并发任务执行,因此是开发异步I/O服务的一个很好的选择。
asyncio模块常用函数和类
- asyncio.create_task(协程对象):将协程包装为任务。
- asyncio.wait(aws, timeout=None, return_when=ALL_COMPLETED):并行运行一个任务列表,aws是任务列表,timeout是等待的秒数,return_when的值可以是WAIT_FIRST_COMPLETED、ALL_COMPLETED或FIRST_EXCEPTION。
- asyncio.gather(aws, *, loop=None, return_exceptions=False):并行运行一个协程列表,会在所有协程执行完成后返回结果。
- asyncio.sleep():模拟时间的等待,是一个异步调用。
- asyncio.Queue():一个异步队列,可以并发的进行put和get操作。
更多的函数和类请查看asyncio的官方文档。
3.说明示例:多任务异步I/O并行执行
接下来我们来看一个简单的示例,实现多任务异步I/O并行执行:
import asyncio
import time
async def do_work(num):
print("start to work {}".format(num))
await asyncio.sleep(1) # 模拟异步I/O
print("work {} has been completed.".format(num))
return num
async def main():
tasks = [asyncio.create_task(do_work(i)) for i in range(1, 11)]
await asyncio.wait(tasks)
if __name__ == '__main__':
start_time = time.time()
asyncio.run(main())
print("time used: ", time.time() - start_time)
在本示例中,我们实现了10个协程任务的异步并行执行,每个任务都等待1秒钟后返回结果。通过asyncio.create_task()将每个异步任务都打包为任务,并将返回的任务列表传递给asyncio.wait()函数,该函数将异步执行所有任务并等待它们全部完成之后才结束。通过time.time()获取程序从开始执行到结束所消耗的时间。
输出结果如下:
start to work 1
start to work 2
start to work 3
start to work 4
start to work 5
start to work 6
start to work 7
start to work 8
start to work 9
start to work 10
work 1 has been completed.
work 2 has been completed.
work 3 has been completed.
work 4 has been completed.
work 5 has been completed.
work 6 has been completed.
work 7 has been completed.
work 8 has been completed.
work 9 has been completed.
work 10 has been completed.
time used: 1.00295090675354
如上输出所示,10个任务都在1秒钟之内完成了,说明它们是异步并行执行的。
4.说明示例:生产者-消费者模式
接下来,我们来看一个更复杂的示例,实现生产者-消费者模式。其中,生产者通过一个异步队列生产数据,而消费者则从队列中读取数据并进行处理。
import asyncio
import random
async def producer(queue, id):
while True:
item = random.randint(0, 99)
print("Producer {} produced {}".format(id, item))
await queue.put(item)
await asyncio.sleep(0.5)
async def consumer(queue, id):
while True:
item = await queue.get()
print("Consumer {} consumed {}".format(id, item))
await asyncio.sleep(1)
async def main():
queue = asyncio.Queue()
producers = [asyncio.create_task(producer(queue, i)) for i in range(3)]
consumers = [asyncio.create_task(consumer(queue, i)) for i in range(2)]
await asyncio.sleep(10) # 等待10秒钟后结束任务
for prod in producers:
prod.cancel() # 取消生产者任务
await asyncio.gather(*producers, return_exceptions=True) # 等待正在运行的任务完成
await queue.join() # 等待队列清空
for cons in consumers:
cons.cancel() # 取消消费者任务
if __name__ == '__main__':
asyncio.run(main())
在本示例中,我们定义了两个协程任务:生产者和消费者,在主函数中创建了一个异步队列,分别创建了3个生产者和2个消费者,每个生产者将随机生成的数据放入队列中,每个消费者从队列中取出数据并进行处理。在主函数中等待10秒钟后结束生产者任务,并等待队列清空后结束消费者任务。
输出结果如下:
Producer 0 produced 10
Consumer 0 consumed 10
Producer 1 produced 12
Consumer 1 consumed 12
Producer 2 produced 20
Consumer 0 consumed 20
Producer 0 produced 63
Consumer 1 consumed 63
Producer 1 produced 74
Producer 0 produced 81
Consumer 0 consumed 74
Consumer 0 consumed 81
Producer 2 produced 88
Consumer 1 consumed 88
.
.
.
Producer 1 produced 12
Consumer 0 consumed 12
Producer 0 produced 65
Consumer 1 consumed 65
Producer 1 produced 45
Consumer 0 consumed 45
如上输出所示,生产者和消费者协同工作,实现了异步的生产和消费,从而构建了生产者-消费者模式。
总结:异步编程是提高代码效率的一种重要的手段,Python的async模块提供了一套完整的异步编程解决方案。了解它的基本使用方法,可以帮助我们更高效地编写异步程序。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python async模块使用方法杂谈 - Python技术站