我有很多任务要执行,并通过生成器提供结果。然而,使用ProcessPoolExecutoras_completed将贪婪地评估结果并将它们全部存储在内存中。在生成器中存储一定数量的结果后,是否有方法阻止?

最佳答案

这样做的目的是把你想处理的东西分成块,我用的例子和ProcessPoolExecutor documentation差不多。

import concurrent.futures
import math
import itertools as it

PRIMES = [
    293,
    171,
    293,
    773,
    99,
    5419,
    293,
    171,
    293,
    773,
    99,
    5419,
    293,
    171,
    293,
    773,
    99,
    5419]


def is_prime(n):
    if n % 2 == 0:
        return False

    sqrt_n = int(math.floor(math.sqrt(n)))
    for i in range(3, sqrt_n + 1, 2):
        if n % i == 0:
            return False
    return True


def main():
    with concurrent.futures.ProcessPoolExecutor() as executor:
        for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):
            print('%d is prime: %s' % (number, prime))

def main_lazy():
    chunks = map(lambda x: it.islice(PRIMES, x, x+4), range(0, len(PRIMES), 4))
    with concurrent.futures.ProcessPoolExecutor() as executor:
        results = zip(PRIMES,
                      it.chain.from_iterable(map(lambda x: executor.map(is_prime, x),
                                                 chunks)))
        for number, prime in (next(results) for _ in range(4)):
            print('%d is prime: %s' % (number, prime))

if __name__ == "__main__":
    main_lazy()

注意mainmain_lazy之间的区别,让我们解释一下:
而不是有一个我们想要处理的所有的列表,我把它分成大小为4的块(使用itertools.islice)是有用的,我们的想法是,不是与执行器映射整个列表,而是映射块。然后只要使用python3 lazymap我们就可以将执行器调用惰性地映射到每个块。因此,我们知道executor.map不是懒惰的,所以当我们请求它时,会立即对块进行评估,但是直到我们不请求其他块时,将不调用该块的executor.map
如您所见,我只请求整个结果列表中的前4个元素,但由于我也使用了itertools.chain,它将只消耗第一个块中的元素,而不计算iterable的其余部分。
因此,既然您想返回生成器,那么从main_lazy函数返回结果就很容易了,您甚至可以抽象块大小(可能需要一个好的函数来获取propper块,但这超出了范围):
def main_lazy(chunk_size):
    chunks = map(lambda x: it.islice(PRIMES, x, x+chunk_size), range(0, len(PRIMES), chunk_size))
    with concurrent.futures.ProcessPoolExecutor() as executor:
        results = zip(PRIMES,
                      it.chain.from_iterable(map(lambda x: executor.map(is_prime, x),
                                                 chunks)))
        return results

08-19 18:03