造轮子程序员 2 从头造轮子:python3 asyncio之 run

前言书接上文 , 本文造第二个轮子 , 也是asyncio包里面非常常用的一个函数run
一、知识准备● 相对于run_until_complete , 改动并不大 , 就是将入口函数重新封装了一下 , 基础知识主要还是run_until_complete的内容
● asyncio.run是Python3.7之后新增的入口函数

二、环境准备组件版本python3.7.7
三、run的实现先来看下官方asyncio的使用方法:
|># more main.pyimport asyncioasync def hello():print('enter hello ...')return 'world'if __name__ == "__main__":rst = asyncio.run(hello())print(rst)|># python3 main.pyenter hello ...return world ...来看下造的轮子的使用方式:
? more main.pyfrom wilsonasyncio import runasync def hello():print('enter hello ...')return 'return world ...'if __name__ == "__main__":ret = run(hello())print(ret)? python3 main.pyenter hello ...return world ...自己造的轮子也很好的运行了 , 下面我们来看下轮子的代码
四、代码解析轮子代码
1)代码组成
|># tree.├── eventloops.py ├── futures.py├── main.py├── tasks.py├── wilsonasyncio.py文件作用eventloops.py事件循环futures.pyfutures对象tasks.pytasks对象wilsonasyncio.py可调用方法集合main.py入口2)代码概览:
eventloops.py
类/函数方法对象作用描述Eventloop事件循环 , 一个线程只有运行一个__init__初始化两个重要对象self._readyself._stoppingself._ready所有的待执行任务都是从这个队列取出来 , 非常重要self._stopping事件循环完成的标志call_soon调用该方法会立即将任务添加到待执行队列run_oncerun_forever调用 , 从self._ready队列里面取出任务执行run_forever死循环 , 若self._stopping则退出循环run_until_complete非常重要的函数 , 任务的起点和终点(后面详细介绍)create_task将传入的函数封装成task对象 , 这个操作会将task.__step添加到__ready队列Handle所有的任务进入待执行队列(Eventloop.call_soon)之前都会封装成Handle对象__init__初始化两个重要对象self._callbackself._argsself._callback 待执行函数主体self._args 待执行函数参数_run待执行函数执行get_event_loop获取当前线程的事件循环_complete_eventloop将事件循环的_stopping标志置位Truerun入口函数新增tasks.py
类/函数方法对象作用描述Task继承自Future , 主要用于整个协程运行的周期__init__初始化对象self._coro  , 并且call_soonself.__step加入self._ready队列self._coro用户定义的函数主体__stepTask类的核心函数ensure_future如果对象是一个Future对象 , 就返回 , 否则就会调用create_task返回 , 并且加入到_ready队列新增futures.py
类/函数方法对象作用描述Future主要负责与用户函数进行交互__init__初始化两个重要对象self._loopself._callbacksself._loop 事件循环self._callbacks 回调队列 , 任务暂存队列 , 等待时机成熟(状态不是PENDING) , 就会进入_ready队列add_done_callback添加任务回调函数 , 状态_PENDING , 就虎进入_callbacks队列 , 否则进入_ready队列set_result获取任务执行结果并存储至_result , 将状态置位_FINISH , 调用__schedule_callbacks__schedule_callbacks将回调函数放入_ready , 等待执行result获取返回值3)执行过程
3.1)入口函数
main.py
async def hello():print('enter hello ...')return 'return world ...'if __name__ == "__main__":ret = run(hello())print(ret)

  • ret = run(hello())直接调用run , 参数是用户函数hello() , 我们看下run的源码
def run(main):loop = get_event_loop()return loop.run_until_complete(main)
  • loop = get_event_loop()获取事件循环
  • return loop.run_until_complete(main)调用run_until_complete
3.2)事件循环启动
def run_until_complete(self, future):future = tasks.ensure_future(future, loop=self)future.add_done_callback(_complete_eventloop, future)self.run_forever()return future.result()
  • 与之前略有不同 , future = tasks.ensure_future(future, loop=self) , 调用了tasks.ensure_future
def ensure_future(coro_or_future, *, loop=None):if isinstance(coro_or_future, Future):return coro_or_futureelse:return loop.create_task(coro_or_future)
  • 如果传入的对象是一个普通函数 , 那就封装成一个task;如果已经是一个future对象 , 那就直接返回 。这一步的目的主要是确保传入的对象 , 是一个Future类型
剩下的部分已经没有什么新鲜的了 , 和run_until_complete一样 , 我们直接跳过...
3.7)执行结果
? python3 main.pyenter hello ...return world ...五、流程总结
造轮子程序员 2 从头造轮子:python3 asyncio之 run

文章插图
六、小结● runrun_until_complete大同小异 , 只不过入口函数做了一些调整 , 使得用户调用更加的便利
● 本文中的代码 , 参考了python 3.7.7中asyncio的源代码 , 裁剪而来
● 本文中代码:代码

至此 , 本文结束
在下才疏学浅 , 有撒汤漏水的 , 请各位不吝赐教...
更多文章 , 请关注我:wilson.chai
【造轮子程序员 2 从头造轮子:python3 asyncio之 run】本文来自博客园 , 作者:wilson排球 , 转载请注明原文链接:https://www.cnblogs.com/MrVolleyball/p/15739907.html
本文版权归作者和博客园共有 , 欢迎转载 , 但未经作者同意必须在文章页面给出原文连接 , 否则保留追究法律责任的权利 。