Невозможно импортировать пользовательский модуль Python, используя многопроцессорную библиотеку - PullRequest
0 голосов
/ 25 апреля 2018

Просто начните использовать библиотеку multiprocessing в моей кодовой базе для параллелизации простого цикла for, где ранее, в последовательном цикле for, я импортировал файл пользовательской конфигурации .py и передал его функциичтобы быть запущенным.

Однако у меня есть проблемы с передачей в модуле конфигурации, чтобы быть parellelised.

Примечание.Есть несколько пользовательских configuration.py, которые я хочу передать различным процессам.

Пример:

def get_custom_config(): 
   config_list = []
   for project_config in configs:
       config = importlib.import_module("config.%s.%s" % (prefix, project_config)
       config_list.append(config)
   return config_list

def print_config(config):
   print config.something_in_config_file

if __name__ = "__main__":
   config_list = get_custom_config()

   pool = mp.Pool(processes=2)
   pool.map(print_config, config_list)

Возвращает:

  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/pool.py", line 251, in map
    return self.map_async(func, iterable, chunksize).get()
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/pool.py", line 567, in get
    raise self._value
cPickle.PicklingError: Can't pickle <type 'module'>: attribute lookup __builtin__.module failed

Какой путь лучшепередачи модуля в параллельный процесс?

1 Ответ

0 голосов
/ 29 апреля 2018

У меня есть для вас возможное решение, но мне не нравится ваш подход.

config = importlib.import_module("config.%s.%s" % (prefix, project_config)

Вы должны попытаться использовать конфигурацию в качестве словаря пар ключ-значение вместо модуля.Или импортируйте его таким образом.

Проблема в том, что functions и modules по умолчанию не выбираются в Python 2.7.Функции по умолчанию выбираются в Python 3.X, а модули - нет.

import importlib
import multiprocessing as mp

configs = ["abc", "def"]
import copy_reg
import types


def _pickle_module(module):
    module_name = module.__name__
    print("pickling" + module_name)
    path = getattr(module, "__file__", None)
    return _unpickle_module, (module_name, path)


def _unpickle_module(module_name, path):
    return importlib.import_module(module_name)

copy_reg.pickle(types.ModuleType, _pickle_module, _unpickle_module)


def get_custom_config():
    config_list = []
    for project_config in configs:
        config = importlib.import_module("config.%s" % (project_config))
        config_list.append(config)
    return config_list


def print_config(config):
    print (vars(config))


if __name__ == "__main__":
    config_list = get_custom_config()

    pool = mp.Pool(processes=2)
    pool.map(print_config, config_list)

Это в основном повторно импортирует модуль в другом процессе, поэтому помните, что вы не делите данные между ними.Это хорошие переменные только для чтения.

Но, как я уже говорил, передача модулей в другой процесс имеет меньше смысла.Попытайтесь исправить свой подход вместо того, чтобы использовать код, который я разместил

PS: решение, вдохновленное Can't pickle: поиск атрибута cv2.BRISK не удалось

...