python 事件循环 loop
2018-12-26 本文已影响0人
宝宝家的隔壁老王
loop
loop 的对象的继承关系
_UnixSelectorEventLoop -> BaseSelectorEventLoop -> BaseEventLoop -> AbstractEventLoop
-
AbstractEventLoop
是抽象基类,事件循环类的属性和方法的定义大都是在这个抽象类中声明,在BaseEventLoop
类中实现。比如:- Running and stopping the eventloop
-
run_forever
# run _run_once() until stop() is called. -
run_until_complete
# Run until future is done. 内部调用 run_forever -
stop
# Stop running the event loop -
close
# Close the event loop. The event loop must not be running. -
shutdown_asyncgens
# Shutdown all active asynchronous generators
-
-
Methods scheduling callbacks. All these return Handles.
-
call_soon
# 将回调绑定到 Handle 对象中,并添加到 _ready 队列中 -
call_later
# 调用 call_at -
call_at
# 将回调绑定到 TimerHandle 对象中,添加到 _scheduled 中 -
time
# 事件循环的时钟时间 -
create_task
# 将协程参数和loop关联生成Task对象 -
create_future
# 创建一个关联 loop 的期物
-
- Running and stopping the eventloop
- 常用的属性:
_closed
_stopping
-
_ready
= collection.queue() - _
scheduled
= [] _default_executor
_internal_fds
_thread_id
-
_clock_resolution
= time.get_clock_info('monotonic').resolution # 时钟分辨率 _selector
- 等
- 常用的设计:
- 1、loop 的创建:
asyncio.get_event_loop()
- 从 events.py 中的全局变量
_running_loop
中取值running_loop, pid
- 如果不存在 running_loop 则使用
DefaultEventLoopPolicy
对象的get_event_loop()
方法获取 loop 值 - 即实例化
_UnixSelectorEventLoop
对象
- 从 events.py 中的全局变量
- 2、loop 的启动:
-
run_forever
- 不接受参数,会一直调用
_run_once()
执行,直到_stopping
值为 True 时停止循环。
- 不接受参数,会一直调用
- run_until_complete
- 接受参数
future
或者coroutine
或者awaitable
对象,使用ensure_future()
包装成future
,调用run_forever
. - future添加
_run_until_complete_cb
为执行完回调方法,此方法会将_stopping
设置为 True
- 接受参数
- 总结下来,就是 loop 会一直循环执行
_run_once
,直到loop._stopping
的值为 True.而_stopping
值一般会在future
的回调函数中设置。
-
- 1、loop 的创建:
-
_run_once
:-
_ready
中存储立即执行的回调,_scheduled
中存储延迟执行的回调 - 1、清理
_scheduled
堆中的无效数据- 如果
_scheduled
中任务大于 100 且cancelled
的占比大于 0.5,则将 cancelled 的任务过滤掉,只保留有效的任务 - 否则将
_scheduled
堆顶的被cancelled
的任务从_scheduled
中去掉
- 如果
- 2、如果 _ready 不为空或者 _stopping 值为 True,则将 timeout 值设为0,否则如果 _scheduled 中值存在,则将 timeout 值设置为 max(0, _scheduled[0]._when - self.time())
- 3、
loop._selector.select(timeout)
获取已就绪的回调事件event_list
- 4、将
event_list
回调事件添加到_ready
队列中 - 5、将
_scheduled
中_when
小于self.time() + self._clock_resolution
值的回调添加到_ready
队列中 - 6、执行
_ready
队列中的回调(因为queue
数据支持并发,故为了避免执行过程中_ready
被添加新的回调,会先使用ntodo
来确保执行的回调个数)
-
DefaultSelector
- 基于
select
模块的高效多路I/O复用 - 常用的方法
-
select()
:- 如果设置
timeout
则等待已注册的文件对象准备就绪直到超时 - 如果没有设置
timeout
,则不会阻塞 - 返回
(key, events)
元组的列表,key
是准备就绪的SelectorKey
对象,其fileobj
即为注册的文件对象。
- 如果设置
-