我试图使用multiprocessing
来调用在不同模块中定义的派生类成员函数。似乎有几个问题涉及从同一模块调用类方法,但没有来自不同模块。例如,如果我有以下结构:
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
方法中完全限定类名,但这只是给出了同样的错误,说multi
未定义。
是否有某种方法可以实现这一点,或者如果我想将multiprocessing
与继承一起使用,我必须重组以使所有类都在同一个包中吗?
答案 0 :(得分:1)
这几乎可以肯定是由于动态调用特定代码的基于eval
的荒谬方法造成的。
在executeWrappedPoolMap
(base.py
)中,您可以使用str
将类的class
名称转换为classType = eval(args[0])
。但是eval
在executeWrappedPoolMap
范围内执行,base.py
位于derived
,并且无法找到base.py
(因为该名称不存在于class
中classInstance.__class__
)。
停止传递名称,并传递classInstance.__class__.__name__
对象本身,传递multiprocessing
而不是eval
; pickle
会为你挑选它,你可以直接在另一端使用它,而不是使用raise
(这几乎总是错误的;它的代码味道最强)。
raise
- 并且被发送回主进程并重新{{1} } -ed。您看到的回溯来自重新NameError
,而不是eval
实际发生的位置(位于public void click_edit_childwindow2(String objectName) {
//Store the current window handle
String winHandleBefore = driver.getWindowHandle();
//Perform the click operation that opens new window
try{
WebElement elemnt = driver.findElement(By.xpath("//*[@id='main']/div[1]/table/tbody/tr[2]/td[6]/button"));
elemnt.click();
driver.findElement(By.xpath("//*[@id='main']/div[1]/table/tbody/tr[2]/td[6]/button")).click();
//Switch to new window opened
for(String winHandle : driver.getWindowHandles()){
driver.switchTo().window(winHandle);
}
// Perform the actions on new window
driver.findElement(By.xpath("//*[@id='myModal']/div/div/div[2]/form/div/div[10]/div/button[1]")).click();
//Close the new window, if that window no more required
//driver.close();
//Switch back to original browser (first window)
driver.switchTo().window(winHandleBefore);
//continue with original browser (first window)
}catch(Exception e){
driver.findElement((By.xpath("//*[@id='logoutForm']/ul/li[2]/a"))).click();
}
}
行)。