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

使用forkserver时无法传递multiprocessing.Manager:无法pickle弱引用对象

forkserver启动方式下传递multiprocessing.Manager触发pickle错误

当使用forkserver作为Python多进程启动方式时,直接把multiprocessing.Manager实例传给子进程,会触发以下错误:

TypeError: cannot pickle 'weakref.ReferenceType' object

示例代码

import multiprocessing

def main():
    multiprocessing.set_start_method('forkserver')
    with multiprocessing.Manager() as manager:
        proc = multiprocessing.Process(target=fun, args=('p1', manager))
        proc.start()
        proc.join()

def fun(name, manager):
    print('fun:', name, manager)

if __name__ == '__main__':
    main()

报错详情

$ /opt/python3.12.6/bin/python3 ./demo_mp_manager_forkserver.py
Traceback (most recent call last):
  File "/home/.../demo_mp_manager_forkserver.py", line 14, in <module>
    main()
  File "/home/.../demo_mp_manager_forkserver.py", line 7, in main
    proc.start()
  File "/opt/python3.12.6/lib/python3.12/multiprocessing/process.py", line 121, in start
    self._popen = self._Popen(self)
                  ^^^^^^^^^^^^^^^^^
  File "/opt/python3.12.6/lib/python3.12/multiprocessing/context.py", line 224, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/python3.12.6/lib/python3.12/multiprocessing/context.py", line 301, in _Popen
    return Popen(process_obj)
           ^^^^^^^^^^^^^^^^^^
  File "/opt/python3.12.6/lib/python3.12/multiprocessing/popen_forkserver.py", line 35, in __init__
    super().__init__(process_obj)
  File "/opt/python3.12.6/lib/python3.12/multiprocessing/popen_fork.py", line 19, in __init__
    self._launch(process_obj)
  File "/opt/python3.12.6/lib/python3.12/multiprocessing/popen_forkserver.py", line 47, in _launch
    reduction.dump(process_obj, buf)
  File "/opt/python3.12.6/lib/python3.12/multiprocessing/reduction.py", line 60, in dump
    ForkingPickler(file, protocol).dump(obj)
TypeError: cannot pickle 'weakref.ReferenceType' object

原因分析

multiprocessing.Manager内部包含弱引用对象,这类对象无法被Python的ForkingPickler序列化。而forkserver启动方式要求所有传递给子进程的参数必须先序列化,再传给forkserver进程去创建子进程,所以直接传递Manager实例会失败。

解决方案

1. 传递Manager创建的共享对象(推荐)

不要直接传Manager实例,而是传它创建的共享代理对象(比如manager.dict()、manager.list()等),这些代理对象支持序列化,可以安全传递给子进程。

修改后的代码:

import multiprocessing

def main():
    multiprocessing.set_start_method('forkserver')
    with multiprocessing.Manager() as manager:
        # 创建共享字典
        shared_dict = manager.dict()
        proc = multiprocessing.Process(target=fun, args=('p1', shared_dict))
        proc.start()
        proc.join()
        print('主进程:', shared_dict)

def fun(name, shared_dict):
    shared_dict['name'] = name
    print('子进程:', name, shared_dict)

if __name__ == '__main__':
    main()

2. 子进程中重新连接到Manager

如果需要在子进程中使用Manager的其他功能(比如动态创建新的共享对象),可以获取Manager的地址,在子进程中重新连接到这个Manager。

修改后的代码:

import multiprocessing
from multiprocessing.managers import SyncManager

def main():
    multiprocessing.set_start_method('forkserver')
    with multiprocessing.Manager() as manager:
        # 获取Manager的地址信息
        manager_addr = manager._address
        proc = multiprocessing.Process(target=fun, args=('p1', manager_addr))
        proc.start()
        proc.join()

def fun(name, manager_addr):
    # 重新连接到已运行的Manager
    manager = SyncManager(address=manager_addr)
    manager.connect()
    # 创建新的共享列表
    shared_list = manager.list([1, 2, 3])
    shared_list.append(name)
    print('子进程:', name, shared_list)

if __name__ == '__main__':
    main()

内容的提问来源于stack exchange,提问作者Messa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 04:20:57