我如何使这个生成器循环?

时间:2019-04-19 18:35:18

标签: python generator

我正在尝试遍历目录并加载所有文件。我试过使用一个生成器加载文件,使用另一个生成器生成批处理,并在内存不足时调用第一个生成器。

def file_gen(b):

    # iterate over my directory and load two audio file at a time

    for n in range(len(b)):
        path_ = os.path.join(os.path.join(path,'Mixtures'), 'Dev')
        os.chdir(os.path.join(path_,b[n]))
        y, _ = librosa.load('mixture.wav', sr=rate)

        path_vox = os.path.join(os.path.join(path,'Sources'), 'Dev')
        os.chdir(os.path.join(path_vox,b[n]))
        x, _ = librosa.load('vocals.wav', sr=rate)

        yield y, x

list_titles = os.listdir(os.path.join(os.path.join(path,'Mixtures'),'Dev'))

gen_file = file_gen(list_titles)

# second generator

def memory_test():

    memory = 0

    if memory == 0:
        a, b = next(gen_file)
        a, _ = mag_phase(spectrogram(a))
        b, _ = mag_phase(spectrogram(b))

        # calculate how many batches I can generate from the file

        memory = a.shape[1]/(n_frames*(time_len-overlap) + time_len)

    for n in range(memory):
        yield memory
        memory = memory -1

test = memory_test()

问题所在的是第二个生成器。理想情况下,我希望两个生成器都无限期地进行迭代(第一个生成器应返回到列表的开头)。

谢谢!

1 个答案:

答案 0 :(得分:1)

itertools.cycle()
一种执行此操作的方法是使用itertools.cycle(),它实际上将存储生成器的结果,然后不断地不断循环它们。 docs

如果您选择这样做,则会消耗大量额外的内存来存储这些结果。


StopIteration除外
作为一种替代方法,您可以try:except StopIteration生成发电机,以将其重置为开始。如果您在用尽的生成器上调用__next__,则生成器始终会引发StopIteration。


编辑:我最初链接到包装函数here,但该示例中的代码实际上不起作用。以下是经过测试可以正常工作的代码,希望对您有所帮助。我的回答是基于相同的概念。

def Primes(max):   # primary generator
    number = 1
    while number < max:
        number += 1
        if check_prime(number):
            yield number

primes = Primes(100)

def primer():   # this acts as a loop and resets your generator
    global primes
    try:
        ok = next(primes)
        return ok
    except StopIteration:
        primes = Primes(100)
        ok = next(primes)
        return ok

while True:   # this is the actual loop continuing forever
    primer()

您会注意到,我们无法隐式引用我们自己的函数以进行自我重置,并且我们也无法使用标准的for loop,因为它会在您可以使用之前先捕获StopIteration ,根据设计[more info]