【问题标题】:multiprocessing.apply_async(myfunc, ...) within a class doesn't seem to call myfunc类中的 multiprocessing.apply_async(myfunc, ...) 似乎没有调用 myfunc
【发布时间】:2017-04-26 16:43:49
【问题描述】:
import multiprocessing


class multiprocessing_issue:
    def __init__(self):
        self.test_mp()

    def print_test(self):
        print "TEST TEST TEST"

    def test_mp(self):
        p = multiprocessing.Pool(processes=4)
        p.apply_async(self.print_test, args=())
        print "finished"


if __name__ == '__main__':
    multiprocessing_issue()

我在上面设置了一个简单的测试,创建一个类,调用apply_async 并使用一个应该打印"TEST TEST TEST" 的函数。当我运行它时,我看到打印了"finished",但它从未像预期的那样打印"TEST TEST TEST"

谁能看到这个简单测试用例中的错误?我已将其设置为重现我在代码中使用它的方式。

Ubuntu 上的 Python 2.7

【问题讨论】:

  • 这是什么版本的 Python?什么操作系统?
  • 在 2.7 和 Windows 上,我也得到“完成”,然后是 ImportError: No module named tmp0jekzi 的所有进程严重崩溃,可能是因为 pool 没有被 if __name__ == '__main__' 屏蔽

标签: python asynchronous multiprocessing


【解决方案1】:

修改test_mp如下:

def test_mp(self):
    p = multiprocessing.Pool(processes=4)
    r = p.apply_async(self.print_test, args=())
    print r.get()

答案会更清楚。

Traceback (most recent call last):
  File "test.py", line 18, in <module>
    multiprocessing_issue()
  File "test.py", line 6, in __init__
    self.test_mp()
  File "test.py", line 14, in test_mp
    print r.get()
  File "/usr/lib/python2.7/multiprocessing/pool.py", line 567, in get
    raise self._value
cPickle.PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed

实例方法cannot be serialized 很容易。 Pickle 协议在序列化函数时所做的只是将其转换为字符串。

In [1]: dumps(function)
Out[1]: 'c__main__\nfunction\np0\n.'

对于子进程来说,由于不同的进程地址空间,很难找到实例方法所引用的正确对象。

dill 之类的模块比 Pickle 做得更好。然而,我不鼓励你混合并发和 OOP,因为逻辑很容易混淆。

【讨论】:

    【解决方案2】:

    啊,在进程之间移动类引用是个问题,如果我在模块级别而不是类级别定义方法,一切正常。

    import multiprocessing
    
    
    class multiprocessing_issue:
        def __init__(self):
            self.test_mp()
    
        def test_mp(self):
            p = multiprocessing.Pool(4)
            r = p.apply_async(mptest, args=())
            r.get()
            print "finished"
    
    
    def mptest():
        print "TEST TEST TEST"
    
    
    if __name__ == '__main__':
        multiprocessing_issue()
    

    【讨论】:

    • 呃,我最后的评论没有意义,我错过了self.test_mp()。我想我不习惯人们使用这样的课程。你会为此创建一个类然后定义__init__ 只是为了运行一个类方法,这对我来说真的没有意义。但我看到你的主要标签是java :P
    • 这没有多大意义,你说得对,好吧,当我开始使用线程进行并行处理时确实如此,但我试图通过切换到多处理而不重写来处理线程问题我所有的代码。陷阱中的陷阱。
    • 对于这个问题的未来参考,这是一篇有用且相关的文章:stackoverflow.com/questions/1816958/…
    • 只有当您调用 r.get() 时,我才会知道为什么会这样。该函数不一定返回任何内容。
    • mptest 上没有返回语句,因此默认返回值为None。我不确定我是否理解这个问题。 @DavidOkwii
    猜你喜欢
    • 1970-01-01
    • 2019-12-04
    • 1970-01-01
    • 2020-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    相关资源
    最近更新 更多