gpt4 book ai didi

python - 基于生成器的协程看似无限递归

转载 作者:行者123 更新时间:2023-12-04 02:06:49 25 4
gpt4 key购买 nike

以下内容摘自 David Beazley 的关于发电机的幻灯片(here 供任何感兴趣的人使用)。

一个 Task定义了一个类,它包装了一个生成 future 的生成器,Task完整的类(无错误处理)如下:

class Task:
def __init__(self, gen):
self._gen = gen

def step(self, value=None):
try:
fut = self._gen.send(value)
fut.add_done_callback(self._wakeup)
except StopIteration as exc:
pass

def _wakeup(self, fut):
result = fut.result()
self.step(result)

在一个示例中,还定义了以下递归函数:
from concurrent.futures import ThreadPoolExecutor
import time

pool = ThreadPoolExecutor(max_workers=8)

def recursive(n):
yield pool.submit(time.sleep, 0.001)
print("Tick :", n)
Task(recursive(n+1)).step()

以下两种情况发生:
  • 从 Python REPL 中,如果我们定义这些(或者如果我们将它们放在文件中,则导入它们),然后使用以下命令启动递归:
    Task(recursive(0)).step()

    它开始打印,似乎已经超出了递归限制。它显然没有超过它,打印堆栈级别表明它在整个执行过程中保持不变。其他事情正在发生,我不太明白。

    注意 : 如果你像这样执行它,你需要杀死 python 进程。
  • 如果我们将所有内容(Taskrecursive)连同:
    if __name__ == "__main__":
    Task(recursive(0)).step()

    然后用 python myfile.py 运行它,它在 7 处停止滴答声(似乎 max_workers 的数量)。


  • 我的问题是它看起来是如何超过递归限制的,为什么它的行为会根据你的执行方式而有所不同?

    该行为同时出现在 Python 3.6.2 和 Python 3.5.4(我猜 3.63.5 家族中的其他人)。

    最佳答案

    让我们从 开始7号 .这就是您已经提到的 worker 数量,标记为 [0..7] . 任务 类需要通过recursive以函数标识符的形式。

    Task(recursive).step(n) 

    代替
    Task(recursive(n)).step()

    这是因为, 递归 函数需要在 pool 中调用环境,而在当前情况下 recursive在主线程本身中进行评估。 time.sleep是当前代码中唯一在任务池中评估的函数。

    代码存在主要问题的一个关键方面是递归。池中的每个线程都依赖于内部函数,将执行上限限制为可用的工作线程数。该功能无法完成,因此新功能无法执行。因此,它在达到递归限制之前就终止了。

    关于python - 基于生成器的协程看似无限递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46529767/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com