我想将多处理任务封装到一个类中。控制和辅助功能都是该类的成员。使用Pool.map_async()
运行工作程序,因此可以在其他工作程序仍在运行时处理结果。处理结果存储在multiprocessing.Queue
中。当Queue是实例变量时,它不起作用,而全局变量或类变量,则它起作用。
示例:
import multiprocessing
class A():
# Queue as instance variable
def __init__(self):
self.qout = multiprocessing.Queue()
def worker(self,x):
self.qout.put(x*x)
def process(self):
values = range(10)
with multiprocessing.Pool() as pool:
res = pool.map_async(self.worker,values)
while (not self.qout.empty() or
not res.ready()):
val = self.qout.get()
print(val)
qoutB = multiprocessing.Queue()
class B():
# Queue as global variable
def __init__(self):
pass
def worker(self,x):
qoutB.put(x*x)
def process(self):
values = range(10)
with multiprocessing.Pool() as pool:
res = pool.map_async(self.worker,values)
while (not qoutB.empty() or
not res.ready()):
val = qoutB.get()
print(val)
class C():
# Queue as Class variable
qout = multiprocessing.Queue()
def __init__(self):
pass
def worker(self,x):
self.qout.put(x*x)
def process(self):
values = range(10)
with multiprocessing.Pool() as pool:
res = pool.map_async(self.worker,values)
while (not self.qout.empty() or
not res.ready()):
val = self.qout.get()
print(val)
现在,当您按如下方式调用类时(将其放在类定义下面)
a=A()
a.process()
不起作用(可能停止等待self.qout.get()
,但是
a=B()
a.process()
和
a=C()
a.process()
有效(打印结果)。为什么?
我在Python documentation中找不到任何相关信息。我没有尝试将队列作为参数传递,但这是应该对用户隐藏的功能。
B选项应该毫无疑问,C并不理想,因为队列将在该类的所有实例之间共享。
注意:已在Linux(Debian,来自存储库的Python 3.5)上进行了测试。
答案 0 :(得分:0)
此不是答案。我发布它是因为它是完整的,可运行的,并且显示了我过去得出的结论,即您的类没有一个是“有效的”,实际上,类A
是唯一的类其while
循环完成(尽管不打印任何内容),而在类B
和C
中,它永远不会结束。
还要注意,我知道由于这三个类的通用性,它们都可能是某个基类的子类-但这不是这个问题的主题(这就是为什么有这么多冗余代码的原因)。
无论如何,对于您的问题,这样的事情会被认为是MCVE-如果只有它产生的结果与您所声称的相吻合,就是这样。
import multiprocessing
TEST_CLASS_NAME = 'B' # Change as necessary.
if TEST_CLASS_NAME == 'A':
class A():
# Queue as instance variable
def __init__(self):
self.qout = multiprocessing.Queue()
def worker(self, x):
self.qout.put(x*x)
def process(self):
values = range(10)
with multiprocessing.Pool() as pool:
res = pool.map_async(self.worker, values)
classname = type(self).__name__
print(classname, '- while loop starting')
while not self.qout.empty() or not res.ready():
val = self.qout.get()
print(val)
print(classname, '- while loop ended')
elif TEST_CLASS_NAME == 'B':
qoutB = multiprocessing.Queue()
class B():
# Queue as global variable
def __init__(self):
self.qout = qoutB
def worker(self, x):
self.qout.put(x*x)
def process(self):
values = range(10)
with multiprocessing.Pool() as pool:
res = pool.map_async(self.worker, values)
classname = type(self).__name__
print(classname, '- while loop starting')
while not self.qout.empty() or not res.ready():
val = self.qout.get()
print(val)
print(classname, '- while loop ended')
elif TEST_CLASS_NAME == 'C':
class C():
# Queue as Class variable
qout = multiprocessing.Queue()
def __init__(self):
pass
def worker(self, x):
self.qout.put(x*x)
def process(self):
values = range(10)
with multiprocessing.Pool() as pool:
res = pool.map_async(self.worker, values)
classname = type(self).__name__
print(classname, '- while loop starting')
while not self.qout.empty() or not res.ready():
val = self.qout.get()
print(val)
print(classname, '- while loop ended')
if __name__ == '__main__':
print('testing class', TEST_CLASS_NAME)
Class = globals()[TEST_CLASS_NAME]
test = Class()
test.process()
print('done')
答案 1 :(得分:0)
SO算法给了我有趣的提示,这是我以前找不到的。
基于this answer,队列不能作为参数传递给正在打开新进程的函数,因为队列不能被腌制。这就是一般self.function()
所做的:它等效于function(self)
。对于类A
,尝试将队列传递给工作程序;与B
和C
中的情况不同,而该过程或多或少地独立于该过程
从this question and answers得出相同的结论。不用说,manager.Queue
在这里也不起作用。
MCVE测试失败
这可能是由于multiprocessing
(see docs)的默认默认启动方法造成的。
答案 2 :(得分:0)
同样,这不是您的问题的答案。但是,我要发布它是因为它使整个问题变得毫无意义—因为您实际上不需要显式创建并使用multiprocessing.Queue
来执行类似的操作。
请改为考虑使用concurrent.futures.ProcessPoolExecutor
完成任务。
例如:
import concurrent.futures
class A_Prime():
def __init__(self):
pass
def worker(self, x):
return x*x
def process(self):
with concurrent.futures.ProcessPoolExecutor() as executor:
classname = type(self).__name__
print(classname, '- calling executor.map')
res = [value for value in executor.map(self.worker, range(10))]
print(classname, '- executor.map finished')
print(' result:', res)
if __name__ == '__main__':
test = A_Prime()
test.process()
print('done')
输出:
A_Prime - calling executor.map
A_Prime - executor.map finished
result: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
done