asyncio 被用作 提供高性能 Python 异步框架的基础,包括网络和网站服务,数据库连接库,分布式任务队列等等。
asyncio 提供一组 高层级 API 用于:
-
并发地 运行 Python 协程 并对其执行过程实现完全控制;
-
执行 网络 IO 和 IPC;
-
控制 子进程;
-
通过 队列 实现分布式任务;
-
同步 并发代码;
此外,还有一些 低层级 API 以支持 库和框架的开发者 实现:
-
使用 transports 实现高效率协议;
-
通过 async/await 语法 桥接 基于回调的库和代码。
event_loop 事件循环:程序开启一个无限的循环,会把一些函数注册到事件循环上。当满足事件发生时,调用相应的协程函数。
asyncio.gather和asyncio.wait
asyncio.gather
能收集协程的结果,且会按照输入协程的顺序保存对应协程的执行结果,而asyncio.wait
的返回值有两项,第一项是完成的任务列表,第二项表示等待完成的任务列表。asyncio.wait
支持接受一个参数return_when
,默认情况下asyncio.wait
会等待全部任务完成(return_when='ALL_COMPLETED')
,它还支持FIRST_COMPLETED
(第一个协程完成就返回)和FIRST_EXCEPTION
(出现第一个异常就返回):
# 定义协程coroutine:调用不会立即执行,而是会返回一个协程对象。协程对象需要注册到事件循环,由事件循环调用。 async def my_task(x): print('Waiting: ', x) return "Done" # 消息循环: 从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,就实现异步IO。 loop = asyncio.get_event_loop() # new_event_loop loop.run_until_complete(my_task(2)) # 堵塞直到所有tasks完成 # 创建task task = loop.create_task(my_task(2)) # 或 task = asyncio.ensure_future(my_task(2)) loop.run_until_complete(task) # 运行任务直到Future完成并返回它的结果,task.result()协程返回值 # 绑定回调 def callback(future): print('Callback: ', future.result()) task.add_done_callback(callback) loop.run_until_complete(task) # coroutine执行结束时会调用回调函数,并通过参数future获取协程执行的结果, 创建的task和回调里的future对象,实际上是同一个对象。 # 在函数定义时用async def foo()
代替@gen.coroutine
装饰器, 用await
代替yield. # 协程遇到await,事件循环会将其挂起,执行别的协程,直到其他协程也挂起或执行完毕,再进行下一个协程的执行。 async def my_task(x): print('Waiting: ', x) await asyncio.sleep(x) return "Done" # ==================================================================== def start_loop(loop): asyncio.set_event_loop(loop) loop.run_forever() def more_work(x): print('More work {}'.format(x)) time.sleep(x) # 同步阻塞 print('Finished more work {}'.format(x)) # 动态添加协程到事件循环: 多线程 new_loop = asyncio.new_event_loop() t = Thread(target=start_loop, args=(new_loop,)) t.start() new_loop.call_soon_threadsafe(more_work, 6) new_loop.call_soon_threadsafe(more_work, 3) # 子线程中进行事件循环的并发操作,同时主线程又不会被block asyncio.run_coroutine_threadsafe(my_task(6), new_loop) asyncio.run_coroutine_threadsafe(my_task(4), new_loop) # master-worker主从模式: 主线程用来监听队列,子线程用于处理队列 t.setDaemon(True) # 设置子线程为守护线程, 当主线程结束的时候,子线程也随机退出。 try: while True: task = rcon.rpop("queue") if not task: time.sleep(1) continue asyncio.run_coroutine_threadsafe(my_task(int(task)), new_loop) except KeyboardInterrupt as e: print(e) new_loop.stop()
loop.run_until_complete(future):协程()、task、asyncio.wait(tasks)、asyncio.gather(*tasks) # 阻塞调用,直到协程运行结束,它才返回。 loop.run_forever() # 一直运行,直到loop.stop被调用. 但不能直接调用,可用gather把多个协程合并成一个future,并添加回调,然后在回调里再去停止 loop。 @asyncio.coroutine把一个generator标记为coroutine类型,然后就把这个coroutine扔到EventLoop中执行。 asyncio.sleep() # 协程,可模拟IO操作如网络请求,文件读取等