在下面的示例代码中,我想获取函数worker的返回值。我该怎么做呢?这个值存储在哪里?
示例代码:
import multiprocessing
def worker(procnum):
'''worker function'''
print str(procnum) + ' represent!'
return procnum
if __name__ == '__main__':
jobs = []
for i in range(5):
p = multiprocessing.Process(target=worker, args=(i,))
jobs.append(p)
p.start()
for proc in jobs:
proc.join()
print jobs
输出:
0 represent!
1 represent!
2 represent!
3 represent!
4 represent!
[<Process(Process-1, stopped)>, <Process(Process-2, stopped)>, <Process(Process-3, stopped)>, <Process(Process-4, stopped)>, <Process(Process-5, stopped)>]
我似乎无法在存储在作业中的对象中找到相关属性。
我想我应该简化上面复制的最简单的例子,在Py3.6上为我工作。最简单的是多处理。池:
import multiprocessing
import time
def worker(x):
time.sleep(1)
return x
pool = multiprocessing.Pool()
print(pool.map(worker, range(10)))
您可以设置池中的进程数,例如,pool (processes=5)。但是,它默认为CPU计数,因此对于CPU受限的任务,请将其保留为空。(I/ o绑定的任务通常适合线程,因为线程大部分都在等待,所以可以共享一个CPU内核。)Pool还应用了分块优化。
(注意,工作方法不能嵌套在方法中。我最初在调用池的方法中定义了工作方法。map,以保持它完全自包含,但随后进程无法导入它,并抛出“AttributeError: Can't pickle local object outer_method..inner_method”。更多的在这里。它可以在类内部。)
(欣赏原文问题指定打印’代表!'而不是time.sleep(),但没有它,我认为一些代码是并发运行时,它不是。)
Py3的ProcessPoolExecutor也是两行(。Map返回一个生成器,所以你需要list()):
from concurrent.futures import ProcessPoolExecutor
with ProcessPoolExecutor() as executor:
print(list(executor.map(worker, range(10))))
使用普通流程:
import multiprocessing
import time
def worker(x, queue):
time.sleep(1)
queue.put(x)
queue = multiprocessing.SimpleQueue()
tasks = range(10)
for task in tasks:
multiprocessing.Process(target=worker, args=(task, queue,)).start()
for _ in tasks:
print(queue.get())
如果您所需要的只是放置和获取,请使用SimpleQueue。在第二个循环进入阻塞队列之前,第一个循环启动所有进程。得到调用。我认为没有任何理由也调用p.join()。
这个例子展示了如何使用multiprocessing的列表。管道实例从任意数量的进程中返回字符串:
import multiprocessing
def worker(procnum, send_end):
'''worker function'''
result = str(procnum) + ' represent!'
print result
send_end.send(result)
def main():
jobs = []
pipe_list = []
for i in range(5):
recv_end, send_end = multiprocessing.Pipe(False)
p = multiprocessing.Process(target=worker, args=(i, send_end))
jobs.append(p)
pipe_list.append(recv_end)
p.start()
for proc in jobs:
proc.join()
result_list = [x.recv() for x in pipe_list]
print result_list
if __name__ == '__main__':
main()
输出:
0 represent!
1 represent!
2 represent!
3 represent!
4 represent!
['0 represent!', '1 represent!', '2 represent!', '3 represent!', '4 represent!']
这种解决方案使用的资源比多进程少。使用
一个管道
至少一个锁
一个缓冲区
一个线程
或者多处理。SimpleQueue使用
一个管道
至少一个锁
查看这些类型的源代码是非常有指导意义的。
一个简单的解决方案:
import multiprocessing
output=[]
data = range(0,10)
def f(x):
return x**2
def handler():
p = multiprocessing.Pool(64)
r=p.map(f, data)
return r
if __name__ == '__main__':
output.append(handler())
print(output[0])
输出:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
对于正在寻找如何使用Queue从进程中获取值的任何人:
import multiprocessing
ret = {'foo': False}
def worker(queue):
ret = queue.get()
ret['foo'] = True
queue.put(ret)
if __name__ == '__main__':
queue = multiprocessing.Queue()
queue.put(ret)
p = multiprocessing.Process(target=worker, args=(queue,))
p.start()
p.join()
print(queue.get()) # Prints {"foo": True}
注意,在Windows或Jupyter Notebook中,使用多线程,您必须将其保存为文件并执行该文件。如果你在命令提示符中这样做,你会看到这样的错误:
AttributeError: Can't get attribute 'worker' on <module '__main__' (built-in)>