流畅的Python书中的协程部分版本太低,而且讲的比较少,这次根据Python3标准库书中实例来学习记录asyncio的使用。
asyncio模块提供了使用次饿成构建并发应用的工具。threading模块通过应用线程并发,mutilprocessing使用系统进程实现并发,asyncio则使用一个单线程单进程的方法来实现并发,应用的各个部分会彼此合作,在最优的时刻显式地切换任务。
asyncio提供的框架以一个事件循环(event loop)为中心,这是一个首类对象,负责高效地处理I/O事件、系统事件、和应用的上下文切换。
就现在本人的了解,一般的io应用中,还是以多线程使用为主,自己在写协程并发的时候,多个协程之间,无法有效的设置条件交出控制权。
唯一能应用的包,就一个aiohttp,如果我想用另外的包实现协程,基本无法做到,然而协程asyncio包就像流畅的Python书中所说,大部分在讲概念和API,
也只能希望后面能有更加丰富的包来配合协程,或者等我哪一天成为高手,写出能配合协程的包。
2、利用协程合作完成多任务
import asyncio async def coroutine(): print(‘in coroutine‘) # 定义事件循环 event_loop = asyncio.get_event_loop() try: print(‘starting coroutine‘) coro = coroutine() print(‘entering event loop‘) # 运行协程 event_loop.run_until_complete(coro) finally: print(‘closing event loop‘) event_loop.close()
/usr/local/bin/python3.7 /Users/shijianzhong/study/t_asyncio/asyncio_coroutine.py starting coroutine entering event loop in coroutine closing event loop Process finished with exit code 0
先通过get_event_loop创建一个默认的事件循环,run_until_complete方法驱动里面的协程,最后关闭事件循环。
从协程返回值
import asyncio # 有返回值 async def coroutine(): print(‘in coroutine‘) return ‘result‘ # 定义事件循环 event_loop = asyncio.get_event_loop() try: print(‘starting coroutine‘) coro = coroutine() print(‘entering event loop‘) # 运行协程,获取值 return_value = event_loop.run_until_complete(coro) print(f‘it returned: {return_value!r}‘) finally: print(‘closing event loop‘) event_loop.close()
/usr/local/bin/python3.7 /Users/shijianzhong/study/t_asyncio/asyncio_coroutine_return.py starting coroutine entering event loop in coroutine it returned: ‘result‘ closing event loop Process finished with exit code 0
串链协程
import asyncio async def outer(): print(‘in outer‘) print(‘waiting for result1‘) # 接收phase1()协程产生的值 result1 = await phase1() print(‘waiting for result2‘) # 接收phase2()协程产生的值 result2 = await phase2(result1) return result1, result2 async def phase1(): print(‘in parse1‘) return ‘result1‘ async def phase2(arg): print(‘in phase2‘) return ‘result2 derived from {}‘.format(arg) event_loop = asyncio.get_event_loop() try: return_value = event_loop.run_until_complete(outer()) print(f‘return_value:{return_value!r}‘) finally: event_loop.close()
/usr/local/bin/python3.7 /Users/shijianzhong/study/t_asyncio/asyncio_coroutine_chain.py in outer waiting for result1 in parse1 waiting for result2 in phase2 return_value:(‘result1‘, ‘result2 derived from result1‘) Process finished with exit code 0
生成器而不是协程
Python3.5开始
async 代替了@asyncio.coroutine
await 代替了 yield from
本人觉得await 还是yield from更加直观。
3、调度常规函数调用
这个使用的话,需要把事件循环传递放入协程中,协程中通过事件循环的方法去激活需要调用的函数。
在传入事件循环的协程里面必须设置asyncio.seleep,要不然协程不会让出控制权,事件循环根本无法激活调用函数。
import asyncio from functools import partial def callback(arg, *, kwarg=‘default‘): print(f‘callback invoked with {arg} and {kwarg}‘) async def main(loop): print(‘registering callbacks‘) # 调用函数,只能传入一个参数,多参数传入调用partial loop.call_soon(callback, 1) # 通过partial传入关键字参数 wrapped = partial(callback, kwarg=‘not default‘) loop.call_soon(wrapped, 2) await asyncio.sleep(.1) event_loop = asyncio.get_event_loop() try: print(‘entering event loop‘) event_loop.run_until_complete(main(event_loop)) finally: event_loop.close()
/usr/local/bin/python3.7 /Users/shijianzhong/study/t_asyncio/asyncio_call_soon.py entering event loop registering callbacks callback invoked with 1 and default callback invoked with 2 and not default Process finished with exit code 0
用Delay调度回调
call_soon是直接调用,call_later()第一个参数可以传入延后的事件,单位为秒,第二个参数为function
在传入事件循环的协程里面必须设置asyncio.seleep,且大于最迟的调用函数时间,要不然协程不会让出控制权,事件循环根本无法激活调用函数。
import asyncio from functools import partial def callback(arg): print(f‘callback invoked {arg}‘) async def main(loop): print(‘registering callbacks‘) # 调用函数,第一个参数传入时间 loop.call_later(0.2, callback, 1) loop.call_later(0.1, callback, 2) # 这个很重要 await asyncio.sleep(.21) event_loop = asyncio.get_event_loop() try: print(‘entering event loop‘) event_loop.run_until_complete(main(event_loop)) finally: print(‘closing event loop‘) event_loop.close()
/usr/local/bin/python3.7 /Users/shijianzhong/study/t_asyncio/asyncio_call_later.py entering event loop registering callbacks callback invoked 2 callback invoked 1 closing event loop Process finished with exit code 0
在指定事件内调度一个回调
实现这个目的的循环依赖的是一个所谓的单调时钟,用loop.time()生成,激活用call_at
import asyncio import time def callback(n, loop): print(f‘callback {n} invoked at {loop.time()}‘) async def main(loop): # 运行结果来看,这now是从0开始的 now = loop.time() print(f‘clock time: {time.time()}‘) print(f‘loop time {now}‘) print(‘registering callbacks‘) # 加0.2秒 loop.call_at(now + .2, callback, 1, loop) # 加0.1 秒 loop.call_at(now + .1, callback, 2, loop) # 马上开始 loop.call_soon(callback, 3, loop) await asyncio.sleep(1) event_loop = asyncio.get_event_loop() try: print(‘entering event loop‘) event_loop.run_until_complete(main(event_loop)) finally: print(‘closing event loop‘) event_loop.close()
/usr/local/bin/python3.7 /Users/shijianzhong/study/t_asyncio/asynvio_call_at.py entering event loop clock time: 1579366496.336677 loop time 0.086557153 registering callbacks callback 3 invoked at 0.086701756 callback 2 invoked at 0.189241196 callback 1 invoked at 0.29037571 closing event loop Process finished with exit code 0
原文地址:https://www.cnblogs.com/sidianok/p/12210857.html