You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 08:37:45