Python 将一系列发生器并联
假设我有如下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)
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上试用,但您是否完全运行我的代码?是的,没有任何修改。