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

Python类中使用multiprocessing报Cannot pickle weakref对象错误

问题根源

你遇到的Cannot pickle 'weakref' object异常,本质是Python多进程启动时的序列化限制:当你把类实例方法作为mp.Process的目标函数,并且传入self对象时,整个类实例会被尝试序列化(pickle)以传递给子进程。而你的ClientHandler实例中包含了manager、lock这类对象,它们内部依赖weakref(比如Manager的代理对象会用弱引用跟踪父进程连接),而weakref是无法被pickle序列化的。

哪怕你把manager、lock移到类外传入,只要传递了整个self对象,实例中任何不可序列化的成员(或其内部引用)都会触发这个异常。第一次启动进程时可能暂时避开,但第二次循环时实例状态变化,彻底触发序列化失败。

解决方案

核心思路是避免传递整个类实例给子进程,只传递子进程需要的独立参数,同时把进程执行逻辑改成不依赖实例的独立函数或静态方法。

方案1:使用全局独立函数

把进程处理逻辑抽成全局函数,仅传入子进程需要的参数(如客户端名、共享列表、锁),完全避开类实例的序列化:

import multiprocessing as mp

# 独立的进程处理函数,不依赖类实例
def process_client(client, shared_list, lock):
    with lock:
        shared_list.append(f"Processed {client}")
    print(f"Completed handling {client}")

class ClientHandler:
    def __init__(self, client_dict):
        self.processes = []
        self.manager = mp.Manager()
        self.shared_list = self.manager.list()
        self.lock = mp.Lock()

        if "ServerGroup" in client_dict and client_dict["ServerGroup"]:
            for client in client_dict["ServerGroup"]:
                # 传入独立函数和必要参数,不传self
                proc = mp.Process(target=process_client, args=(client, self.shared_list, self.lock))
                self.processes.append(proc)

    def start(self):
        for proc in self.processes:
            proc.start()
        # 可选:等待所有进程结束
        for proc in self.processes:
            proc.join()

方案2:使用类静态方法

如果希望逻辑和类绑定,可以用静态方法(不需要实例引用),同样只传必要参数:

import multiprocessing as mp

class ClientHandler:
    def __init__(self, client_dict):
        self.processes = []
        self.manager = mp.Manager()
        self.shared_list = self.manager.list()
        self.lock = mp.Lock()

        if "ServerGroup" in client_dict and client_dict["ServerGroup"]:
            for client in client_dict["ServerGroup"]:
                # 调用静态方法,传入参数
                proc = mp.Process(target=ClientHandler._process_client, args=(client, self.shared_list, self.lock))
                self.processes.append(proc)

    @staticmethod
    def _process_client(client, shared_list, lock):
        with lock:
            shared_list.append(f"Processed {client}")
        print(f"Completed handling {client}")

    def start(self):
        for proc in self.processes:
            proc.start()
        for proc in self.processes:
            proc.join()
关键注意点
  • 永远不要把整个类实例(self)传给子进程,只传递子进程必须的、可序列化的参数。
  • mp.Manager创建的共享对象(如list、dict)本身是可跨进程传递的代理对象,直接传入即可,不需要包裹在实例里。
  • 避免在进程目标函数中使用绑定到实例的方法,除非你能确保整个实例完全可序列化(这在包含多进程原语时几乎不可能)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 13:25:04