Iva*_*lev 4 python coroutine python-3.x python-asyncio
我正在使用Python 3 asyncio框架评估不同的模式以定期执行(实际的睡眠/延迟以简化),我有两段代码表现得很差,我无法解释原因.yield from正如我所料,第一个版本用于递归调用自身耗尽大约1000次迭代的堆栈.第二个版本递归调用协程,但委托实际的事件循环执行到asyncio.async并且不会耗尽堆栈.你能详细解释为什么第二个版本没有使用堆栈吗?执行此协程的两种方式有什么区别?
第一版(收益率):
@asyncio.coroutine
def call_self(self, i):
print('calling self', i)
yield from self.call_self(i + 1)
Run Code Online (Sandbox Code Playgroud)
第二个版本(asyncio.async):
@asyncio.coroutine
def call_self(self, i):
print('calling self', i)
asyncio.async(self.call_self(i + 1))
Run Code Online (Sandbox Code Playgroud)
dan*_*ano 11
第一个例子,使用yield from,实际上阻止每个实例,call_self直到它的递归调用call_self返回.这意味着调用堆栈会持续增长,直到用完堆栈空间.正如您所提到的,这是明显的行为.
第二个例子,使用asyncio.async,不会阻止任何地方.因此,每个实例call_self在运行后立即退出asyncio.async(...),这意味着堆栈不会无限增长,这意味着您不会耗尽堆栈.相反,通过将事件循环包装在事件循环的迭代中,可以执行asyncio.async调度.call_selfasyncio.Task
这是__init__for Task:
def __init__(self, coro, *, loop=None):
assert iscoroutine(coro), repr(coro) # Not a coroutine function!
super().__init__(loop=loop)
self._coro = iter(coro) # Use the iterator just in case.
self._fut_waiter = None
self._must_cancel = False
self._loop.call_soon(self._step) # This schedules the coroutine to be run
self.__class__._all_tasks.add(self)
Run Code Online (Sandbox Code Playgroud)
调用self._loop.call_soon(self._step)是实际使协程执行的原因.因为它以非阻塞的方式发生,所以调用堆栈call_self永远不会超出对Task构造函数的调用.然后,下一个实例call_self循环在下一次迭代时启动事件循环(在前一次call_self返回时启动,假设事件循环中没有其他任何内容正在运行),完全超出前一个call_self实例的上下文.
| 归档时间: |
|
| 查看次数: |
3420 次 |
| 最近记录: |