无法使用多进程库导入自定义 python 模块
Can't import custom python module using multiprocess library
刚开始在我的代码库中使用 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)
Returns:
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
将模块传递给并行进程的最佳方式是什么?
我确实有适合您的解决方案,但我不喜欢您的方法。
config = importlib.import_module("config.%s.%s" % (prefix, project_config)
您应该尝试将配置作为键值对字典而不是模块。或者以这种方式导入。
问题是 functions
和 modules
在 Python 2.7 中默认是不可 picklable 的。在 Python 3.X 中,函数默认是可 picklable 的,而模块仍然不是。
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:解决方案灵感来自
刚开始在我的代码库中使用 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)
Returns:
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
将模块传递给并行进程的最佳方式是什么?
我确实有适合您的解决方案,但我不喜欢您的方法。
config = importlib.import_module("config.%s.%s" % (prefix, project_config)
您应该尝试将配置作为键值对字典而不是模块。或者以这种方式导入。
问题是 functions
和 modules
在 Python 2.7 中默认是不可 picklable 的。在 Python 3.X 中,函数默认是可 picklable 的,而模块仍然不是。
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:解决方案灵感来自