- 主题:asyncio的鸡生蛋问题
用async def定义了一个函数,它返回一个coroutine
想调用它,正常情况下需要用await关键字
但是await关键字本身必须用在async定义的函数内
这就有了鸡生蛋问题
搜了一下发现:
asyncio.run可以处理这个
定义在asyncio/runners.py里
我觉得这玩意就是我之前提问想要的答案
但是我不知道它自己是怎么规避鸡生蛋的语法限制的
查看源码发现:
asyncio.run()为了伺候一个coroutine,单独生成了一个event loop并调用其
run_until_complete()方法,而该方法在设置完callback之后就运行了run_forever()方
法
run_until_complete()方法调用ensure_future()方法,把coroutine包装为future
而ensure_future调用了loop.create_task()方法
在create_task()中,task类初始化时,调用loop的call_soon()将自身注册到loop中去了
所以后来run_forever()处理的tasks里就有这个task/future/coroutine了
最核心的位置:
tasks.py def__step_run_and_handle_result函数
使用coroutine的send方法进行了实际执行
从而规避了“必须使用await”的语法限制
--
修改:JulyClyde FROM 139.227.18.*
FROM 139.227.18.*
Python 的协程其实你很早就开始用了。就是以前的 yield. 后来在 python 3.5 这个版本里面,把 yield 改个名字叫 await,就发布了 python 的协程。当然实际上是 yield from,但是也差不多。真是改个名字,整个代码量我记得不超过 100 行。
协程说破天了就是让两个函数来回跳着执行。可以用 yield/await,也可以用汇编指令的 jmp 来回跳。
但为啥你不理解现在这些呢。因为协程存在这么多年了一直没啥用。
协程还必须和事件循环配合,才能用于异步 IO. 异步框架定义了一个事件循环协程,当程序员写的协程碰到 IO 事件时就跳到事件循环协程里面,事件发生后,再跳回程序员的协程继续读写。
这就是为什么你写了一大堆 async/await 不能直接用。必须在程序员的最顶层,再启动事件循环协程。
asyncio.run() 干的事情就是启动一个额外的事件循环协程,等待你的协程结束,然后关闭事件循环协程。
【 在 JulyClyde 的大作中提到: 】
: 用async def定义了一个函数,它返回一个coroutine
: 想调用它,正常情况下需要用await关键字
: 但是await关键字本身必须用在async定义的函数内
: ...................
--
FROM 59.61.197.*
【 在 JulyClyde 的大作中提到: 】
: 用async def定义了一个函数,它返回一个coroutine
: 想调用它,正常情况下需要用await关键字
: 但是await关键字本身必须用在async定义的函数内
: ...................
其实, 就是用到生成器的实现方式。
send + yield, 变成了send + await,
for 循环, 变成了消息队列循环。
--
FROM 115.171.155.*
新文档里明确说generator不算coroutine吧?
【 在 hgoldfish 的大作中提到: 】
: Python 的协程其实你很早就开始用了。就是以前的 yield. 后来在 python 3.5 这个
: 版本里面,把 yield 改个名字叫 await,就发布了 python 的协程。当然实际上是
: yield from,但是也差不多。真是改个名字,整个代码量我记得不超过 100 行。
: 协程说破天了就是让两个函数来回跳着执行。可以用 yield/await,也可以用汇编指令
: 的 jmp 来回跳。
: 但为啥你不理解现在这些呢。因为协程存在这么多年了一直没啥用。
: ...................
--
FROM 139.227.18.*
嗯嗯
挖深了才明白
感觉asyncio包的层次好深啊
各种概念:
coroutine、future、task、Handle
尤其是,future、task居然都不是独立存在的,生成对象的时候其实已经绑定了一个
event loop了,但是它居然是个独立的类。这个写法好奇怪……
【 在 poggy 的大作中提到: 】
: 其实, 就是用到生成器的实现方式。
: send + yield, 变成了send + await,
: for 循环, 变成了消息队列循环。
: ...................
--
FROM 139.227.18.*