使用pathos多进程结合共享列表时触发‘digest sent was rejected’认证错误
问题根源与解决方案
这个AuthenticationError是pathos的ProcessingPool和Python标准库multiprocessing.Manager的交互方式导致的,并非dill本身的问题。我来详细拆解原因并给出可行的解决办法:
为什么会出现这个错误?
multiprocessing.Manager启动的后台服务器进程,会使用一个默认的认证密钥(authkey,通常基于当前用户的登录名生成)来验证连接的合法性。而pathos的ProcessingPool内部会自行生成一个随机的authkey来初始化进程池。
当你的代码里,子进程需要访问self.my_list(Manager创建的共享列表代理)时,pathos的dill会序列化整个self对象并传递给子进程。子进程反序列化后尝试连接Manager服务器,但用的是Pool生成的随机authkey,和Manager的默认authkey不匹配,直接触发了认证失败的错误。
三种可行的解决方案
1. 统一Manager和Pool的authkey
手动设置相同的认证密钥,让两者的进程间通信能通过验证:
import os import math from multiprocessing import Manager, current_process from pathos.multiprocessing import ProcessingPool class MyComplex: def __init__(self, x): self._z = x * x def me(self): return math.sqrt(self._z) class Starter: def __init__(self): # 获取当前进程的authkey,作为统一密钥 self.authkey = current_process().authkey # 给Manager指定相同的authkey manager = Manager(authkey=self.authkey) self.my_list = manager.list() def _f(self, value): print(f"{value.me()} on {os.getpid()}") # 注意:这里要调用me(),而不是存方法引用(避免额外序列化问题) self.my_list.append(value.me()) def start(self): names = [MyComplex(x) for x in range(100)] # 创建Pool时传入相同的authkey with ProcessingPool(authkey=self.authkey) as pool: pool.map(self._f, names) if __name__ == '__main__': starter = Starter() starter.start()
2. 避免序列化包含Manager代理的self对象
用functools.partial把共享列表直接绑定为函数参数,不让self被序列化传到子进程:
import os import math from multiprocessing import Manager from pathos.multiprocessing import ProcessingPool from functools import partial class MyComplex: def __init__(self, x): self._z = x * x def me(self): return math.sqrt(self._z) class Starter: def __init__(self): manager = Manager() self.my_list = manager.list() def _f(self, shared_list, value): print(f"{value.me()} on {os.getpid()}") shared_list.append(value.me()) def start(self): names = [MyComplex(x) for x in range(100)] # 把共享列表绑定到函数参数上 func = partial(self._f, self.my_list) with ProcessingPool() as pool: pool.map(func, names) if __name__ == '__main__': starter = Starter() starter.start()
3. 改用pathos自带的Manager(最省心)
pathos提供了自己的Manager实现,和ProcessingPool使用相同的authkey与序列化机制,完全避免兼容性问题:
import os import math from pathos.multiprocessing import ProcessingPool, Manager class MyComplex: def __init__(self, x): self._z = x * x def me(self): return math.sqrt(self._z) class Starter: def __init__(self): # 使用pathos的Manager manager = Manager() self.my_list = manager.list() def _f(self, value): print(f"{value.me()} on {os.getpid()}") self.my_list.append(value.me()) def start(self): names = [MyComplex(x) for x in range(100)] with ProcessingPool() as pool: pool.map(self._f, names) if __name__ == '__main__': starter = Starter() starter.start()
总结
优先推荐第三种方案,直接用pathos自带的Manager,不需要额外配置就能完美兼容。如果必须使用标准库的Manager,前两种方法也能解决authkey不匹配的问题。
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

