Доброго вам дня,
Сегодня я перемещал код с threading
на multiprocess
. Казалось, все в порядке, пока я не получил следующую ошибку:
Error
Traceback (most recent call last):
File "run.py", line 93, in <module>
main()
File "run.py", line 82, in main
emenu.executemenu(components, _path)
File "/home/s1810979/paellego/lib/execute/execute_menu.py", line 29, in executemenu
e.executeall(installed, _path)
File "/home/s1810979/paellego/lib/execute/execute.py", line 153, in executeall
pool.starmap(phase2, args)
File "/usr/lib64/python3.4/multiprocessing/pool.py", line 268, in starmap
return self._map_async(func, iterable, starmapstar, chunksize).get()
File "/usr/lib64/python3.4/multiprocessing/pool.py", line 608, in get
raise self._value
File "/usr/lib64/python3.4/multiprocessing/pool.py", line 385, in _handle_tasks
put(task)
File "/usr/lib64/python3.4/multiprocessing/connection.py", line 206, in send
self._send_bytes(ForkingPickler.dumps(obj))
File "/usr/lib64/python3.4/multiprocessing/reduction.py", line 50, in dumps
cls(buf, protocol).dump(obj)
_pickle.PicklingError: Can't pickle <class 'module'>: attribute lookup module on builtins failed
Код
execute.py
def executeall(components, _path):
args = []
manager = multiprocessing.Manager()
q = manager.Queue()
resultloc = '/some/result.log'
for component in components:
for apkpath, resultpath in zip(execonfig.apkpaths, execonfig.resultpaths):
args.append((component,apkpath,resultpath,q,)) #Args for subprocesses
cores = askcores()
with multiprocessing.Pool(processes=cores) as pool:
watcher = pool.apply_async(lgr.log, (resultloc+'/results.txt', q,))
pool.starmap(phase2, args)
component.py
class Component(object):
def __init__(self, installmodule, runmodule, installerloc, installationloc, dependencyloc):
self.installmodule = installmodule
self.runmodule = runmodule
self.installerloc = installerloc
self.installationloc = installationloc
self.dependencyloc = dependencyloc
self.config = icnf.Installconfiguration(installerloc+'/conf.conf')
#lots of functions...
installconfig.py
class State(Enum):
BEGIN=0 #Look for units
UNIT=1 #Look for unit keypairs
KEYPAIR=3
class Phase(Enum):
NONE=0
DEPS=1
PKGS=2
class Installconfiguration(object):
def __init__(self, config):
dictionary = self.reader(config) #Fill a dictionary
#dictionary (key:Phase, value: (dictionary key: str, job))
self.deps = dictionary[Phase.DEPS]
self.pkgs = dictionary[Phase.PKGS]
job.py
class Job(object):
def __init__(self, directory=None, url=None):
self.directory = directory if directory else ''
self.url = url if url else ''
Как видите, я передаю компонент в качестве аргумента function phase2(component, str, str, multiprocess.manager.Queue())
.
Второй и третий аргумент конструктора component
- это модули, импортированные с importlib
.
Что я пробовал
Я новичок в python, но не в программировании. Вот что я попробовал:
- Поскольку в самой ошибке не указывалось, в чем именно проблема, я попытался удалить аргументы, чтобы выяснить, какие из них не могут быть засолены: Удалите
component
, и все работает нормально, так что, похоже, это является причиной проблемы , Однако мне нужно, чтобы этот объект был передан моим процессам.
- Я искал в Интернете несколько часов, но не нашел ничего, кроме базовых руководств по многопроцессорной обработке и объяснений о том, как работает рассол. Я нашел это , говорящее, что это должно работать, но не на окнах или чем-то. Тем не менее, он не работает на Unix (который я использую)
Мои идеи
Насколько я понял, ничто не говорит о том, что я не могу отправить класс, содержащий два модуля importlib. Я не знаю, в чем именно проблема с классом component
, но модуль importlib как члены - единственные нерегулярные вещи. Вот почему я считаю, что проблема возникает здесь.
Вопрос
Знаете ли вы, почему класс, содержащий модули, не подходит для «засолки»? Как можно лучше понять, почему и где происходят ошибки Can't pickle <class 'module'>
1054 *
больше код
Полный исходный код для этого можно найти на https://github.com/Sebastiaan-Alvarez-Rodriguez/paellego
Вопросы ко мне
Пожалуйста, оставляйте комментарии с просьбой дать разъяснения / дополнительные фрагменты кода / ??? если вы хотите, чтобы я отредактировал этот вопрос
Последний запрос
Я бы хотел, чтобы решения использовали только стандартную библиотеку python, желательно python 3.3. Кроме того, требование моего кода заключается в том, что он работает в системах Unix.
Заранее спасибо
Редактировать
В соответствии с запросом приведен минимальный пример, который значительно упрощает проблему:
main.py (вы можете выполнить как python main.py foo)
#!/usr/bin/env python
import sys
import importlib
import multiprocessing
class clazz(object):
def __init__(self, moduly):
self.moduly = moduly
def foopass(self, stringy):
self.moduly.foo(stringy)
def barpass(self, stringy, numbery):
self.moduly.bar(stringy)
print('Second argument: '+str(numbery))
def worker(clazzy, numbery):
clazzy.barpass('wow', numbery)
def main():
clazzy = clazz(importlib.import_module(sys.argv[1]))
clazzy.foopass('init')
args = [(clazzy, 2,)]
with multiprocessing.Pool(processes=2) as pool:
pool.starmap(worker, args)
if __name__ == "__main__":
main()
foo.py (должен находиться в том же каталоге, что и для предложенного выше вызова):
#!/usr/bin/env python
globaly = 0
def foo(stringy):
print('foo '+stringy)
global globaly
globaly = 5
def bar(stringy):
print('bar '+stringy)
print(str(globaly))
Это дает ошибку при запуске: TypeError: can't pickle module objects
Теперь мы знаем, что травление объектов модуля (к сожалению) невозможно.