管道一个迭代器到多个消费者?

2024-06-28 20:02:59 发布

您现在位置:Python中文网/ 问答频道 /正文

是否有可能在多个用户之间“管道”消耗一台发电机?在

例如,通常有以下模式的代码:

def consumer1(iterator):
    for item in iterator:
        foo(item)

def consumer2(iterator):
    for item in iterator:
        bar(item)

myiter = list(big_generator())
v1 = consumer1(myiter)
v2 = consumer2(myiter)

在这种情况下,多个函数完全使用同一个迭代器,因此有必要在列表中缓存迭代器。由于每个使用者都耗尽迭代器,itertools.tee是无用的。在

我经常看到这样的代码,我总是希望我能让消费者按顺序一次消费一个项目,而不是缓存整个迭代器。E、 g.:

  1. consumer1消耗myiter[0]
  2. consumer2消耗myiter[0]
  3. consumer1消耗myiter[1]
  4. consumer2消耗myiter[1]
  5. 等等。。。在

如果我编一个语法,它应该是这样的:

^{pr2}$

您可以使用线程或多处理和teed迭代器来接近,但是线程以不同的速度消耗,这意味着tee中缓存的deque值可能会非常大。这里的重点不是利用并行性或加速任务,而是避免缓存迭代器的大段。在

在我看来,如果不修改消费者,这可能是不可能的,因为控制流在消费者中。然而,当使用者实际使用迭代器控制传递到迭代器的next()方法时,那么也许有可能以某种方式反转控制流,以便迭代器一次阻塞一个使用者,直到它可以将它们全部输入为止?在

如果这是可能的,我还不知道怎么做。有什么想法吗?在


Tags: 代码infordef使用者消费者item线程
2条回答

由于不更改消费者代码的限制(即在其中有一个循环),您只剩下两个选项:

  1. 问题中已经包含的方法是:在内存中缓存生成的项,然后对它们进行多次迭代。在
  2. 在一个线程中运行每个消费者,并实现某种同步-itertools.tee,其中一个缓冲区大小为1,它阻止服务项目i+1,直到项目{}被提供给所有消费者。在

没有其他选择。您无法实现以下所有目标,因为它们相互矛盾:

  1. 有发电机的
  2. 有一个循环来消耗它
  3. 然后,(串行-)在前一个循环完成后,有另一个循环再次消耗所有循环
  4. 在使用O(1)项时只在内存(或磁盘等)中保留它们
  5. 不再生(即不重新创建发电机)

如果要重用生成的项,则必须将它们存储在的某个位置。在

如果更改消费者的代码是可以接受的,那么@monkey的解决方案显然是最简单和最直接的。在

这不管用吗?或者您需要整个迭代器,这样对每个迭代器的一个副本就不能工作了?如果是这样的话,那么我认为你要么必须创建一个副本,要么生成两次列表?在

for item in big_generator():
    consumer1.handle_item(item)
    consumer2.handle_item(item)

相关问题 更多 >