开关发电机输出

时间:2012-12-08 14:11:53

标签: python generator

我有一项任务,我需要根据某些条件“切换”发电机中间流量的输出。

让我们说我们有一个生成器从某些无限来源产生数据。每次我们从发生器读取1GB数据时,我们都会将输出切换到其他读卡器。

input = MyInfiniteGenerator()
Reader1(input) # does something with the first gigabyte of data
Reader2(input) # does something with the second gigabyte of data
...

当我们将输出从Reader1切换到Reader2时,应该关闭Reader1。我无法改变读者的行为方式,只是迭代输入。

此问题类似于旋转文件日志。

2 个答案:

答案 0 :(得分:1)

我建议将您的发电机包装在另一台只能读取您想要的数量的发电机中。 itertools.islice应该做得很好:

import itertools

gen = someInfiniteGenerator()

while True:
    slice = itertools.islice(gen, 1000000) # reads one million items from gen
    reader = Reader(slice) # consumes all of the slice

唯一可能出现的问题是,如果gen永远结束(也就是说,它会引发StopIteration),除非得到一个空的生成器,否则读取器将会检测到它。如果这是可能性,您可以使用额外级别的生成器来解决它,在生成任何内容之前检查生成器中至少有一个项目:

class EmptyGenerator(Exception):
    pass

def notEmptyGen(gen):
    try:
        first = next(gen)
        yield first
    except StopIteration: # empty source generator
        raise EmptyGenerator()

    yield from gen

答案 1 :(得分:0)

您可以执行类似

的操作
input_chunk = (i for _, i in zip(xrange(chunk_size), input)) # `range` in Python3

或者,或许更一般地说,

from itertools import takewhile    
input_chunk = takewhile(condition, input)

并将input_chunk提供给Reader1

condition必须是一个带有一个参数的函数 - input的项目。

另请注意,inputbuilt-in function的名称,并将其用作变量名称,您将隐藏它。

itertools.takewhile上的文档。