以下使用python 2.7.9不起作用,但也不会抛出任何错误或异常。是否存在错误,或者是否可以在类中使用多处理?
from multiprocessing import Pool
def testNonClass(arg):
print "running %s" % arg
return arg
def nonClassCallback(result):
print "Got result %s" % result
class Foo:
def __init__(self):
po = Pool()
for i in xrange(1, 3):
po.apply_async(self.det, (i,), callback=self.cb)
po.close()
po.join()
print "done with class"
po = Pool()
for i in xrange(1, 3):
po.apply_async(testNonClass, (i,), callback=nonClassCallback)
po.close()
po.join()
def cb(self, r):
print "callback with %s" % r
def det(self, M):
print "method"
return M+2
if __name__ == "__main__":
Foo()
跑步打印:
done with class
running 1
running 2
Got result 1
Got result 2
编辑:这似乎是相关的,但它使用.map
,而我特别需要使用apply_async
,这似乎与多处理如何与类实例一起工作(例如,我没有一个picklnig错误,就像许多与此相关的许多其他问题) - Python how to do multiprocessing inside of a class?
答案 0 :(得分:1)
默认情况下,进程不共享状态或内存,每个进程都是一个独立的程序。您需要1)使用线程2)使用specific types capable of sharing state或3)设计程序以避免共享状态并依赖返回值。
更新
您的代码中有两个问题,一个是屏蔽另一个问题。
1)你没有对apply_async
的结果做任何事情,我发现你正在使用回调,但你仍然需要抓住结果并处理它们。因为您没有这样做,所以您没有看到第二个问题导致的错误。
2)对象的方法无法传递给其他进程...当我第一次发现这个时,我真的很生气,但有一个简单的解决方法。试试这个:
from multiprocessing import Pool
def _remote_det(foo, m):
return foo.det(m)
class Foo:
def __init__(self):
pass
po = Pool()
results = []
for i in xrange(1, 3):
r = po.apply_async(_remote_det, (self, i,), callback=self.cb)
results.append(r)
po.close()
for r in results:
r.wait()
if not r.successful():
# Raises an error when not successful
r.get()
po.join()
print "done with class"
def cb(self, r):
print "callback with %s" % r
def det(self, M):
print "method"
return M+2
if __name__ == "__main__":
Foo()
答案 1 :(得分:0)
我非常确定它可以在一个类中使用,但你需要保护对Foo
内部句子的调用,如:
if name == "__main__":
以便它只在主线程中被调用。您可能还必须更改类的__init__
函数,以便它接受池作为参数而不是创建池。
我刚试过这个
from multiprocessing import Pool
#global counter
#counter = 0
class Foo:
def __init__(self, po):
for i in xrange(1, 300):
po.apply_async(self.det, (i,), callback=self.cb)
po.close()
po.join()
print( "foo" )
#print counter
def cb(self, r):
#global counter
#print counter, r
counter += 1
def det(self, M):
return M+2
if __name__ == "__main__":
po = Pool()
Foo(po)
我想我知道现在的问题是什么。 Python不是多线程的;全局解释器锁防止这种情况。 Python正在使用多个进程,因此池中的子进程无法访问主进程的标准输出。
子进程也无法修改变量counter
,因为它存在于不同的进程中(我尝试使用注释掉的counter
行并取消注释)。现在,我确实记得看到全局状态变量被池中的进程改变的情况,所以我不知道所有的细节。我知道,一般来说,拥有像这样的全局状态变量是一个坏主意,如果没有其他原因,它们可能导致竞争条件和/或浪费时间锁定并等待访问全局变量。 / p>