我正在尝试使用多处理
来调用在不同模块中定义的派生类成员函数。从同一模块调用类方法似乎有几个问题,但从不同模块调用类方法没有问题。例如,如果我有以下结构:
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__()
派生.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
方法中完全限定类名,但这只会给出相同的错误,即 multi
未定义。
是否有某种方法可以实现此目的,或者如果我想将多处理
与继承一起使用,我必须重新构造以将所有类放在同一个包中吗?
最佳答案
这几乎肯定是由可笑的基于 eval
的动态调用特定代码的方法引起的。
在 executeWrappedPoolMap
(在 base.py
中)中,将类的 str
名称转换为 class
本身带有 classType = eval(args[0])
。但eval
是在executeWrappedPoolMap
的作用域内执行的,该作用域位于base.py
中,找不到衍生
(因为 base.py
中不存在该名称)。
停止传递名称,而传递class
对象本身,传递classInstance.__class__
而不是classInstance.__class__.__name__
; multiprocessing
将为您腌制它,您可以直接在另一端使用它,而不是使用 eval
(这几乎总是错误的;这是最强烈的代码味道)。
顺便说一句,回溯不是很有帮助的原因是异常在工作线程中引发,被捕获,pickle
-ed,然后发送回主进程并重新加注
-ed。您看到的回溯来自重新raise
,而不是NameError
实际发生的位置(位于eval
行中)。
关于python - 多处理和模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34202173/