python multiprocessing------PicklingError: Can't pickle

当在Python的multiprocessing中遇到PicklingError时,通常是因为传递给进程的函数或参数不可序列化。可序列化的数据类型包括None、布尔值、数字、字符串等。类中的方法无法直接序列化,需要将它们定义在模块的顶层。解决此类问题的方法是确保所有传递给进程的函数都在模块顶层定义,并且所有参数都是可序列化的。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://bbs.chinaunix.net/thread-4111379-1-1.html

import multiprocessing

class someClass(object):
    def __init__(self):
        pass

    def f(self, x):
        return x*x

    def go(self):
        pool = multiprocessing.Pool(processes=4)             
        #result = pool.apply_async(self.f, [10])     
        #print result.get(timeout=1)           
        print pool.map(self.f, range(10))

注意:如果出现
PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed

数据序列化
https://zhidao.baidu.com/question/525917268.html
https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/00138683221577998e407bb309542d9b6a68d9276bc3dbe000
应该是说一个数据结构,比如二叉树之类,序列化以后会变成一个char数组或者一个string字符串这样,方便你存到文件里面或者通过网络传输。然后要恢复的时候就是“反序列化”,把文件里读出来/从网络收到的char数组或者string恢复成一棵二叉树或者其他什么东西。主要就是方便保存

可以被序列化的类型有:
https://zhidao.baidu.com/question/619353578954760372.html
* None,True 和 False;
* 整数,浮点数,复数;
* 字符串,字节流,字节数组;
* 包含可pickle对象的tuples,lists,sets和dictionaries;
* 定义在module顶层的函数:
* 定义在module顶层的内置函数;
* 定义在module顶层的类;
* 拥有dict()或setstate()的自定义类型;

https://stackoverflow.com/questions/8804830/python-multiprocessing-pickling-error

The problem is that the pool methods all use a queue.Queue to pass tasks to the worker processes. Everything that goes through the queue.Queue must be pickable, and foo.work is not picklable since it is not defined at the top level of the module.
It can be fixed by defining a function at the top level

大意是类中的方法不能被序列化,而进程中的参数或者函数必须被序列化,所以报错

解决:
import multiprocessing

def func(x):
    return x*x

class someClass(object):
    def __init__(self,func):
        self.f = func

    def go(self):
        pool = multiprocessing.Pool(processes=4)
        #result = pool.apply_async(self.f, [10])
        #print result.get(timeout=1)
        print pool.map(self.f, range(10))

a=someClass(func)
a.go()

defining a function at the top level
将进程需要调用的函数变成定义在module顶层的函数

解决过程中又出现的问题:
1. con = multiprocessing.Process(target=self.connect, args=(k, metrics, request, return_dict, ))
同样是PicklingError: Can’t pickle错误
原因是:

type(metrics)
<type 'dict'>

虽然metrics的类型是dict但是里面的具体内容是
'vmware_vm_net_transmitted_average': <prometheus_client.core.GaugeMetricFamily object at 0x7161650>
也会报PicklingError: Can’t pickle

可能是里里面的<prometheus_client.core.GaugeMetricFamily object at 0x7161650>不能被序列化

这个错误是因为在使用 Python 多进程时,需要将传递的对象序列化,而 rockx.RockX.Object 这个对象无法被序列化。解决办法是将这个对象转换成可以序列化的类型,比如字典或者元组,然后再传递。你可以参考下面的示例代码: ```python import rockx # 将 RockX.Object 对象转换成字典 def obj_to_dict(obj): return { 'class_name': obj.__class__.__name__, 'params': obj.__dict__ } # 将字典转换成 RockX.Object 对象 def dict_to_obj(d): if d['class_name'] == 'Object': obj = rockx.RockX.Object() obj.__dict__.update(d['params']) return obj return d # 在多进程中使用转换后的对象 if __name__ == '__main__': import multiprocessing as mp # 创建 RockX.Object 对象 obj = rockx.RockX.Object() # 将对象转换成字典 obj_dict = obj_to_dict(obj) # 使用 multiprocessing.Process 创建进程 p = mp.Process(target=worker, args=(obj_dict,)) # 启动进程 p.start() # 等待进程结束 p.join() # 在进程中将字典转换成 RockX.Object 对象 def worker(obj_dict): # 将字典转换成 RockX.Object 对象 obj = dict_to_obj(obj_dict) # 在进程中使用对象 ... ``` 在这个示例代码中,我们定义了两个函数 obj_to_dict 和 dict_to_obj,用于将 RockX.Object 对象转换成字典和将字典转换成 RockX.Object 对象。在主进程中,我们先将 RockX.Object 对象转换成字典,然后将字典传递给子进程。在子进程中,我们再将字典转换成 RockX.Object 对象,然后在进程中使用这个对象。这样就可以避免 "Can't pickle <class 'rockx.RockX.Object'>: attribute lookup Object on rockx.RockX failed" 这个错误了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值