多处理和模块

multiprocessing and modules

我正在尝试使用 multiprocessing 调用在不同模块中定义的派生 class 成员函数。似乎有几个问题涉及从同一模块调用 class 方法,但从不同模块调用 none 方法。例如,如果我有以下结构:

main.py
multi/
    __init__.py (empty)
    base.py
    derived.py

main.py

from multi.derived import derived
from multi.base import base

if __name__ == '__main__':
    base().multiFunction()
    derived().multiFunction()

base.py

import multiprocessing;

# The following two functions wrap calling a class method
def wrapPoolMapArgs(classInstance, functionName, argumentLists):
    className = classInstance.__class__.__name__
    return zip([className] * len(argumentLists), [functionName] * len(argumentLists), [classInstance] * len(argumentLists), argumentLists)

def executeWrappedPoolMap(args, **kwargs):
    classType = eval(args[0])
    funcType = getattr(classType, args[1])
    funcType(args[2], args[3:], **kwargs)

class base:
    def multiFunction(self):
        mppool = multiprocessing.Pool()
        mppool.map(executeWrappedPoolMap, wrapPoolMapArgs(self, 'method', range(3)))

    def method(self,args):
        print "base.method: " + args.__str__()

derived.py

from base import base

class derived(base):
    def method(self,args):
        print "derived.method: " + args.__str__()

输出

base.method: (0,)
base.method: (1,)
base.method: (2,)
Traceback (most recent call last):
  File "e:\temp\main.py", line 6, in <module>
    derived().multiFunction()
  File "e:\temp\multi\base.py", line 15, in multiFunction
    mppool.map(executeWrappedPoolMap, wrapPoolMapArgs(self, 'method', range(3)))
  File "C:\Program Files\Python27\lib\multiprocessing\pool.py", line 251, in map
    return self.map_async(func, iterable, chunksize).get()
  File "C:\Program Files\Python27\lib\multiprocessing\pool.py", line 567, in get
    raise self._value
NameError: name 'derived' is not defined

我已经尝试在 wrapPoolMethodArgs 方法中完全限定 class 名称,但这只会给出相同的错误,说 multi 未定义。

有什么方法可以实现这一点,或者如果我想使用 multiprocessing 继承,我必须重组以将所有 class 放在同一个包中吗?

这几乎可以肯定是由基于 eval 的动态调用特定代码的荒谬方法引起的。

executeWrappedPoolMap 中(在 base.py 中),您将 class 的 str 名称转换为 class 本身 classType = eval(args[0]) .但是eval是在executeWrappedPoolMap的范围内执行的,在base.py,找不到derived(因为名字在[=12=中不存在) ]).

停止传递名称,传递 class 对象本身,传递 classInstance.__class__ 而不是 classInstance.__class__.__name__multiprocessing 会为你 pickle,你可以直接在另一端使用它,而不是使用 eval(这几乎总是错误的;它是最强烈的代码味道)。

顺便说一句,回溯不是很有用的原因是异常在 worker 中引发、捕获、pickle-ed,然后发送回主进程并重新 raise-编辑。您看到的回溯来自 re-raise,而不是 NameError 实际发生的地方(在 eval 行)。