Multiprocessing Manager无法传递给其他进程及Pool.map场景使用问题问询
报错根因
BaseManager实例内部包含AuthenticationString类型的敏感属性,该类型出于安全设计禁止被pickle序列化。Pool.map传递参数时会对所有传入对象做序列化,因此绑定了Manager实例的partial对象会触发上述报错。直接给Pool.Process传参可正常运行,是因为multiprocessing对Process的参数走了特殊的fork继承逻辑,不需要对Manager做完整序列化。
解决方案(兼容map功能)
首选方案是利用Pool的initializer初始化参数传递Manager,不需要额外序列化,修改后可正常运行,代码示例如下:
from multiprocessing.managers import BaseManager from multiprocessing import Pool class MyManager(BaseManager): pass class MyClass(): def __init__(self, i): self.i = i # 子进程全局变量用于接收Manager实例 process_manager = None def init_pool(init_manager): global process_manager process_manager = init_manager def my_fun(i): return process_manager.MyClass(i) MyManager.register('MyClass', MyClass) if __name__ == '__main__': manager = MyManager() manager.start() # 初始化Pool时传入初始化函数和参数 with Pool(processes=4, initializer=init_pool, initargs=(manager,)) as p: res = [r.i for r in p.map(my_fun, list(range(10)))] print(res)
该方案通过Pool初始化阶段将Manager实例传递给所有子进程的全局空间,子进程内的任务函数直接调用即可,不需要每次通过map传参,Windows、Linux平台均可正常兼容。
如果不想使用全局变量,也可以选择显式传递Manager的服务地址与认证密钥,在子进程内重新连接Manager,该方案更适合跨主机调用的场景。
内容的提问来源于stack exchange,提问作者Jeor
相关产品推荐
相关产品推荐

