• 彻底解决python多进程can‘t pickle问题


    原因分析:

    这个问题,出在主进程向新进程(子进程)传递的参数不可被序列化上,那么,只要传递的参数可以序列化,问题就不存在了(貌似是废话,但理解这句话至关重要)。

    假设不可被pickle的类是Task,而task是一个不可被pickle的Task的实例化对象。

    不论使用multiprocessing.Process()还是multiprocessing.Pool(),都是主进程向子进程的worker传递参数,这些参数要确保是可序列化的即可。

    • 错误方式:先将task创建完成,再由主进程提供给子进程的worker运行,就会报错can’t pickle
    • 正确方式:将创建task这一动作,放在worker中,而向worker传递的参数(即worker接受的参数)是Python的内置类型,如字符串

    总结要点:

    1. worker(args)要创建在if __name__ == __main__之外,确保是在顶层(通俗理解就是def worker(args)前不能有空格,确保无缩进),否则会提示不可pickle
    2. worker是在新进程中运行的,除了接受参数的过程涉及由主进程向新进程传递外,worker的body部分与主进程没有半毛钱关系,也不在主进程中运行
    3. worker传递的参数args必须是可被序列化的,这点很容易做到

    一例胜千言

    错误方式

    class Task:
        def __init__(self,s):
            self.s = s
        def run(self):
            pass       
    
    # 不可被pickle的对象,创建在主进程中,等待由主进程向新进程传递,这个过程一定涉及task的序列化
    tasks = [Task(str(i)) for i in range(5)]
    
    def worker(task):
        task.run()
        
    if __name__ == "__main__":
        with multiprocessing.Pool() as pool:
            # 因为tasks中的元素(具体的task)都是不可被pickle的,所以由主进程向新进程传递时,就会报错can't pickle
            pool.map(worker, tasks)    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    正确代码

    class Task:
        def __init__(self,s):
            self.s = s
        def run(self):
            pass       
    
    # 这里的s_list中的每一个元素,都是Python内置支持的类型,所以一定可被序列化    
    s_list = [str(i) for i in range(5)]
    
    def worker(s):
        # 重要区别,创建对象的过程是在worker中完成,而不是在主进程中
        task = Task(s)
        task.run()
        
    if __name__ == "__main__":
        with multiprocessing.Pool() as pool:
            # 因为s_list中的元素(具体的s)都是可被pickle的,所以由主进程向新进程传递时,就不会报错can't pickle
            pool.map(worker, s_list) 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
  • 相关阅读:
    Prometheus认证访问-grafana配置-安装mysql和redis的节点监控
    基于Three.js实现三维空间中的箭头移动动画
    贪心算法之单源最短路径
    EMP.DLL是什么东西?怎么解决EMP.DLL文件缺失
    C++学习笔记03-类的默认成员函数
    面试:封装DOM
    阿里云服务器采用AMD CPU处理器ECS实例规格详解
    ajax中的和后端交互的put、patch、delete请求
    【SpringMVC】Jrebel 插件实现热部署与文件上传
    数据结构(C语言版)概念、数据类型、线性表
  • 原文地址:https://blog.csdn.net/weixin_42787086/article/details/133589904