学习一时爽,一直学习一直爽
Hello,大家好,我是 もうり,一个从无到有的技术+语言小白。
https://docs.python.org/zh-cn/3/library/asyncio.html
一说并发,你肯定想到了多线程 / 多进程模型,没错,多线程 / 多进程,正是解决并发问题的经典模型之一
协程:是单线程下的并发,又称微线程。 英文名 Coroutine。
协程比线程的单位更小——协程
注意协程这个概念完全是程序员自己想出来的东西,它对于操作系统来说根本不存在。操作系统只知道进程和线程。
从
import timedef print_num(num): print("Maoli is printing " + str(num) + " nows" ) time.sleep(1) print("Maoli prints" + str(num) + " OK")def main(nums): for num in nums: print_num(num)%time main([i for i in range(1,6)])Maoli is printing 1 nowsMaoli prints1 OKMaoli is printing 2 nowsMaoli prints2 OKMaoli is printing 3 nowsMaoli prints3 OKMaoli is printing 4 nowsMaoli prints4 OKMaoli is printing 5 nowsMaoli prints5 OKWall time: 5 s
将上面代码改为协程版
注意 py 版本 3.7 以上
import asyncioasync def print_num(num): print("Maoli is printing " + str(num) + " nows" ) await asyncio.sleep(1) print("Maoli prints" + str(num) + " OK")async def main(nums): for num in nums: await print_num(num)%time asyncio.run(main([i for i in range(1,6)]))Maoli is printing 1 nowsMaoli prints1 OKMaoli is printing 2 nowsMaoli prints2 OKMaoli is printing 3 nowsMaoli prints3 OKMaoli is printing 4 nowsMaoli prints4 OKMaoli is printing 5 nowsMaoli prints5 OKWall time: 5.01 s
asyncio.run() 函数用来运行最高层级的入口点 "main()" 函数
await 是同步调用等待一个协程。以下代码段会在等待 1 秒后打印 num,
如果一个对象可以在 await 语句中使用,那么它就是 可等待 对象
协程中的还一个重要概念,任务(Task)
如果写一个数字是一个任务,那么毛利我要完成 5 个任务
毛利我写个 1-5 都这么慢,不行,我要加速写
asyncio.create_task() 函数用来并发运行作为 asyncio 任务 的多个协程。
import asyncioasync def print_num(num): print("Maoli is printing " + str(num) + " nows" ) await asyncio.sleep(1) print("Maoli prints" + str(num) + " OK")async def main(nums): tasks = [asyncio.create_task(print_num(num)) for num in nums] for task in tasks: await task%time asyncio.run(main([i for i in range(1,6)]))Maoli is printing 1 nowsMaoli is printing 2 nowsMaoli is printing 3 nowsMaoli is printing 4 nowsMaoli is printing 5 nowsMaoli prints1 OKMaoli prints3 OKMaoli prints5 OKMaoli prints2 OKMaoli prints4 OKWall time: 1.01 s
还可以写成 await asyncio.gather(*tasks)
这种方法
import asyncioasync def print_num(num): print("Maoli is printing " + str(num) + " nows" ) await asyncio.sleep(1) print("Maoli prints" + str(num) + " OK")async def main(nums): tasks = [asyncio.create_task(print_num(num)) for num in nums] await asyncio.gather(*tasks)%time asyncio.run(main([i for i in range(1,6)]))
*tasks 解包列表,将列表变成了函数的参数;与之对应的是, ** dict 将字典变成了函数的参数。
asyncio 队列被设计成与 queue 模块类似。
import asyncioimport randomasync def consumer(queue, id): while True: val = await queue.get() print('{} get a val: {}'.format(id, val)) await asyncio.sleep(1)async def producer(queue, id): for i in range(5): val = random.randint(1, 10) await queue.put(val) print('{} put a val: {}'.format(id, val)) await asyncio.sleep(1)async def main(): # 创建队列 queue = asyncio.Queue() # 消费者1号 consumer_1 = asyncio.create_task(consumer(queue, 'consumer_1')) # 消费者2号 consumer_2 = asyncio.create_task(consumer(queue, 'consumer_2')) # 生产者1号 producer_1 = asyncio.create_task(producer(queue, 'producer_1')) # 生产者2号 producer_2 = asyncio.create_task(producer(queue, 'producer_2')) # stop 10秒 await asyncio.sleep(10) consumer_1.cancel() consumer_2.cancel() await asyncio.gather(consumer_1, consumer_2, producer_1, producer_2, return_exceptions=True)%time asyncio.run(main())
协程的写法简洁清晰,把 async / await 语法和 create_task 结合来用。