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 loop2
True
# get_event_loop()获得以后context默认的event loop,若没有则新生成一个。
>>>
>>> loop.run_until_complete(main(loop, 'loop.run_until_complete'))
loop.run_until_complete : match
Current 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 match
Current 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 match
Current 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 loop7
True
# 此时须要给以后context再set一个event loop才行
>>>
>>> loop4.run_until_complete(main(loop6, 'loop.run_until_complete'))
loop.run_until_complete : not match
Current 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 match
Current 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/…
发表回复