python:python中异步的使用姿势 ## async 在python中,可以利用asyncio包异步处理IO等操作,极大的增加吞吐。 asyncio的底层依赖的是一个IOLoop。最简单的用法如下: ``` import asyncio loop = asyncio.get_event_loop() async def test(): print("test is run") await asyncio.sleep(5) print("test is run over") for i in range(5): loop.create_task(test()) loop.run_forever() ``` 带async的函数是一个协程,可以随时调用create_task来将协程包装为任务。 await关键词顾名思义,就是async wait。它将异步化为同步。在同个协程中,await的上下文有序。也就是说,它会“阻塞”住当前协程(但不需要担心,其它协程还是会在loop下好好的运行),直到await后的协程返回结果。 单实例下一种常见的“错误”写法如下: ``` import asyncio loop = asyncio.get_event_loop() async def test(): print("test is run") await asyncio.sleep(5) print("test is run over") async def run(): for i in range(5): await test() loop.create_task(run()) loop.run_forever() ``` 在这个程序中, test is run 会每隔5秒出现一次。单实例下,await将异步化为了同步。具体奥妙,须慢慢体会。 create_task 不会阻塞住协程,如果需要等待任务完成,可以在协程中await task. ``` import asyncio loop = asyncio.get_event_loop() async def test(): print("test is run") await asyncio.sleep(5) print("test is run over") async def run(): tasks = [] for i in range(5): tasks.append(loop.create_task(test())) await asyncio.wait(tasks) # 也可以 # for task in tasks: # await task print("over") loop.create_task(run()) loop.run_forever() ``` 在框架中,我们不需要关心loop。所以在实作中,需要上下文有序,则用await等待。不需要,则直接create_task。 ## 手工实现 如果知道协程的原理,则很容易写出简单的“协程” 比如传统的生产消费模式: ``` import time prev_fib = 1 fib = 1 def producer(): global fib while 1: yield fib def consumer(): global fib global prev_fib while 1: now_fib = yield print(fib) fib = now_fib + prev_fib prev_fib = now_fib p1 = producer() p2 = consumer() next(p2) while 1: item = next(p1) p2.send(item) time.sleep(0.1) ``` 来自 大脸猫 写于 2017-10-31 17:34 -- 更新于2020-10-19 13:06 -- 0 条评论