时间:2016-09-15 01:05:14

标签: python class multiprocessing

以下使用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?

2 个答案:

答案 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>