Asyncio的事件循环

事件循环

在事件循环中,咱们能够:
- 注销,执行和勾销调用
- 启动子过程,和内部过程进行通信
- 把耗时的函数调用委托给线程池解决

实质上。所有的事件循环都是期待事件产生,而后执行相应的调用。在此之前,咱们须要把行将产生的事件和对应执行的调用互相关联。

事件循环和线程的关系

从asyncio event loop policy文档,咱们得悉, event loop policy是一个过程全局对象,管制对该过程内所有event loop的治理。
过程的全局policy定义了该policy管控的context的含意,在每个context中治理离开独立的event loop. 默认的policy定义的context就是以后的线程, 也就是说不同的线程是不同的context,因而有不同的event loop。
通过定制event loop policy扭转get_event_loop(), set_event_loop(),new_event_loop()的默认行为。
每个context中只有一个running event loop

asyncio中 asyncio.run(),asyncio.get_event_loop(), asyncio.new_event_loop,asyncio.set_event_loop()的场景

asyncio.get_event_loop()

若:

  • 以后线程为主线程,
  • 以后线程没有启动event loop,
    -以后线程没有调用async.set_event_loop(None)

调用asyncio.get_event_loop()办法会生成一个新的默认event loop,并设置为以后线程的事件循环。
此时,get_event_loop()相当于:

loop = asyncio.new_event_loop()asyncio.set_event_loop(loop)

若以后context有默认的event loop,并且没有被set_event_loop(None),则返回默认event loop,

aysncio.run()

调用该办法,会生成新的event loop并在办法调用完结时敞开该event loop。应该作为编写的普通用户异步程序的主入口存在。该办法原则上最好只调用一次。此时asyncio.run()相当于:

new_loop = asyncio.new_event_loop()asyncio.set_event_loop(new_loop)new_loop.run_until_complete(coro)asyncio.set_event_loop(None)new_loop.close()

示例总结:

>>> import asyncio>>> async def main(loop,desc: str):...     cur_loop = asyncio.get_running_loop()...     if cur_loop is loop:...         print(desc, ': match')...     else:...         print(desc, ': not match')...     print(f'Current running loop is :{id(cur_loop)}' )>>> loop = asyncio.get_event_loop()>>> loop2 = asyncio.get_event_loop()>>>loop is loop2True # get_event_loop()获得以后context默认的event loop,若没有则新生成一个。>>>>>> loop.run_until_complete(main(loop, 'loop.run_until_complete'))loop.run_until_complete : matchCurrent running loop is :140127062748856>>> loop.close()  #close 以后的默认循环>>>>>> loop.run_until_complete(main(loop, 'loop.run_until_complete'))Traceback (most recent call last):  File "<stdin>", line 1, in <module>  File "/home/shone/miniconda2/envs/python37/lib/python3.7/asyncio/base_events.py", line 560, in run_until_complete    self._check_closed()  File "/home/shone/miniconda2/envs/python37/lib/python3.7/asyncio/base_events.py", line 480, in _check_closed    raise RuntimeError('Event loop is closed')RuntimeError: Event loop is closed# close()之后,这个event loop就彻底费了,然而,只有不调用set_event_loop(otherloop), 则loop仍然是以后context的默认event loop。>>>>>> loop3 = asyncio.new_event_loop()>>> loop3.run_until_complete(main(loop, 'loop.run_until_complete'))loop.run_until_complete : not matchCurrent running loop is :140127033794456# loop3是新生成的event loop ,然而并非以后context的默认event loop>>>>>> loop3.stop()>>> loop3.is_closed()False>>> loop3.run_until_complete(main(loop, 'loop.run_until_complete'))loop.run_until_complete : not matchCurrent running loop is :140127033794456# stop 一个event loop 只是暂停event loop , 还能再用。>>>>>> asyncio.set_event_loop(None)>>> loop5 = asyncio.get_event_loop()Traceback (most recent call last):  File "<stdin>", line 1, in <module>  File "/home/shone/miniconda2/envs/python37/lib/python3.7/asyncio/events.py", line 644, in get_event_loop    % threading.current_thread().name)RuntimeError: There is no current event loop in thread 'MainThread'# 调用set_event_loop(None) 后,执行get_event_loop会产生例外,>>>>>> loop6 = asyncio.new_event_loop()>>> asyncio.set_event_loop(loop6)>>> loop7 = asyncio.get_event_loop()>>> loop6 is loop7True# 此时须要给以后context再set一个event loop才行>>>>>> loop4.run_until_complete(main(loop6, 'loop.run_until_complete'))loop.run_until_complete : not matchCurrent running loop is :140127033408816# 一个context中能够生成多个event loop,然而默认的event loop 只有一个。并且,只有event loop不被close(), 任何一个event loop都能run,然而正running的event loop只有一个>>>>>> asyncio.run(main(loop6, 'asyncio.run'))asyncio.run : not matchCurrent running loop is :140127033529008>>> loop8 = asyncio.get_event_loop()Traceback (most recent call last):  File "<stdin>", line 1, in <module>  File "/home/shone/miniconda2/envs/python37/lib/python3.7/asyncio/events.py", line 644, in get_event_loop    % threading.current_thread().name)RuntimeError: There is no current event loop in thread 'MainThread'.# 调用asyncio.run()相当于从新设定以后contex的默认loop , 应用完后,close以后的默认loop>>>

以上代码实例,起源自 

https://gist.github.com/kaelz...
https://www.programcreek.com/...