2015-12-10 7 views
1

Я пытаюсь использовать 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 с наследованием?

ответ

1

Это почти наверняка вызвано смехотворным подходом к динамическому вызову определенного кода.

В executeWrappedPoolMapbase.py), преобразование str имени класса к самому class с classType = eval(args[0]). Но eval выполнен в пределах executeWrappedPoolMap, который находится в base.py, и не может найти derived (потому что имя не существует в base.py).

Остановить передачу имени и передать объект class, минуя classInstance.__class__ вместо classInstance.__class__.__name__; multiprocessing рассортирует его для вас, и вы можете использовать его прямо на другом конце, вместо того, чтобы использовать eval (что почти всегда неправильно, это запах кода самого сильного сорта).

BTW, причина, по которой трассировка не очень полезна, заключается в том, что исключение возникает у рабочего, пойманного, pickle -ed и отправлено обратно в основной процесс и обратно raise -ed. Отслеживание, которое вы видите, происходит от этого значения raise, а не там, где фактически произошло NameError (которое находилось в линии eval).

+0

У меня изначально возникли проблемы с травлением экземпляра, поэтому я заменил его на eval имени вместо этого, но, очевидно, это не требуется. Просто передайте экземпляр, как вы предлагаете работы - спасибо. – MuertoExcobito

Смежные вопросы