【问题标题】:Can't import custom python module using multiprocess library无法使用多进程库导入自定义 python 模块
【发布时间】:2018-04-25 14:54:12
【问题描述】:

刚开始在我的代码库中使用 multiprocessing 库来并行化一个简单的 for 循环,以前,在串行 for 循环中,我将导入自定义配置 .py 文件并将其传递给函数运行。

但是,我在传入要并行化的配置模块时遇到问题。

注意。我想将多个自定义 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

将模块传递给并行进程的最佳方式是什么?

【问题讨论】:

  • 你想只使用python2.7还是Python 3也可以?如果是这样,也可以使用 Python 3 试试这个
  • @TarunLalwani 我只想在可能的情况下使用 python2.7!

标签: python-2.7 pickle python-multiprocessing


【解决方案1】:

我确实为您提供了可能的解决方案,但我不喜欢您的方法。

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

您应该尝试将 config 作为键值对的字典,而不是作为模块。或者以这种方式导入。

问题在于 functionsmodules 在 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 <type 'cv2.BRISK'>: attribute lookup cv2.BRISK failed

【讨论】:

  • 如果我以只读方式使用模块,使用这种方法可以吗?或者这只是不好的做法,相反,我应该按照您的建议将模块导入字典作为更好的做法? (也感谢工作代码!)
  • 您可以在运行时导入配置,这没有问题。但是当你向池发送config_list 时,它不应该包含模块,要么发送实际配置,要么只传递模块名称,让每个进程加载自己的配置副本
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-02-20
  • 2021-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-24
  • 2018-03-24
相关资源
最近更新 更多