Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 将一系列发生器并联_Python_Parallel Processing_Stream_Generator - Fatal编程技术网

Python 将一系列发生器并联

Python 将一系列发生器并联,python,parallel-processing,stream,generator,Python,Parallel Processing,Stream,Generator,假设我有如下Python流处理代码: def F1(stream): for x in stream: yield f1(x) def F2(stream): for x in stream: yield f2(x) def F3(stream): for x in stream: yield f3(x) def F4(stream): for x in stream: yield f4(x)

假设我有如下Python流处理代码:

def F1(stream):
    for x in stream:
        yield f1(x)

def F2(stream):
    for x in stream:
        yield f2(x)

def F3(stream):
    for x in stream:
        yield f3(x)

def F4(stream):
    for x in stream:
        yield f4(x)


for x in F4(F3(F2(F1(range(1000000))))):
    print(x)
这大致相当于Unix中的
range 1000000 | F1 | F2 | F3 | F4
(假设使用
range
命令),但在Unix中,管道中的每个进程并行运行


有没有一种简单的方法来并行化Python代码?

你需要管道和黑魔法,Python两者都有

from multiprocessing import Process, Pipe


def F1(stream):
    for x in stream:
        yield str(x)+'a'

def F2(stream):
    for x in stream:
        yield x+'b'

def F3(stream):
    for x in stream:
        yield x+'c'

def F4(stream):
    for x in stream:
        yield x+'d'



class PIPE_EOF:
    pass

class IterableConnection(object):
    def __init__(self, pipe):
        self.pipe = pipe

    def __iter__(self):
        return self

    def __next__(self):
        try:
            ret = self.pipe.recv()
            if ret == PIPE_EOF:
                raise StopIteration
            return ret
        except EOFError:
            raise StopIteration

    def next(self):
        return self.__next__()


def parallel_generator_chain(*args, **kwargs):
    if 'data' in kwargs:
        data = kwargs['data']
    else:
        raise RuntimeError('Missing "data" argument.')

    def decorator(func, _input, _output):
        def wrapper(*args, **kwargs):
            for item in func(_input):
                _output.send(item)
            _output.send(PIPE_EOF)
        return wrapper

    for func in args:
        in_end, out_end = Pipe(duplex = False)
        in_end = IterableConnection(in_end)
        func = decorator(func, data, out_end)
        p = Process(target = func)
        p.start()
        data = in_end

    for output in data:
        yield output



if 'xrange' not in globals():
    xrange = range


if __name__ == '__main__':
    for x in parallel_generator_chain(xrange, F1, F2, F3, F4, data=100000000):
        print(x)

#for x in F4(F3(F2(F1(range(1000000))))):
#    print(x)

注意:我看到了,但我的实际用例比简单的
映射图要复杂一些:
F1
F2
F3
、和
F4
中的每一个都在处理值的过程中累积了一些状态。如果有人想看到完整的代码,如果它们累积了状态,它就会打开,您如何保证它们甚至可以并行化?因为它们累积的状态是每个函数的局部状态(函数之间不共享),这是一个很好的问题。不幸的是Python可能不是正确的答案。很抱歉耽搁了您的时间,谢谢您的回复!我一直在尝试让您的代码正常工作,但没有成功(Python3.3)。您的
decorator
函数不会返回任何内容,代码也不会产生任何输出;因此,我向装饰器添加了一个返回,但我得到了
\u pickle.PicklingError:Can't pickle:attribute lookup builtins.function失败
。代码是否为您正常运行?再次感谢,你说得对。我写它更像是一个概念证明,而不是一个工作代码,所以我没有测试它。然而,我已经用一个工作版本编辑了我的文章。它应该可以与Python2和Python3一起使用;我将在Unix上试用它,并随时通知您。我无法在Windows上试用,但您是否完全运行我的代码?是的,没有任何修改。