python多进程编程之新建子进程的实现机制

       在Unix系统下,python的multiprocessing模块下,直接通过分支一个新的进程,并调用进程对象的run方法来实现;这就相当于直接复制了父进程当前的状态,然后在此基础上在独立内存中运行。由于需要复制父进程的状态,所以如果父进程本身占用内存较大,那么新建的进程会加倍的增加内存占用。

       而在Windows下,python的multiprocessing模块是通过新建一个python解释器,并通过管道向新的进程传入pickle后的进程对象,然后再unpickle这个对象并调用其run方法来实现。pickle是python编程里的一种序列化对象的方式,而序列化可以认为是将对象进行转化成一种可以储存或者可以传输的过程,unpickle也就是反序列化,则是相反的过程,即把序列化后的对象转化成可以直接在内存中使用的过程。并不是所有的对象都是pickable的,一般的,Python的内置数据结构都是pickable的,对于定义在模块top-level的函数和类也是可以pickle的,所谓模块top-level指的是可以直接从模块访问到的,而不能是类中的函数或者函数中的函数,所以被函数装饰器装饰的函数便是不可pickle的,因为该函数实际上是装饰器函数返回的函数,不是top-level的函数;此外,lambda函数也是不可pickle的,因为lambda函数是匿名函数,实际上共享名称lambda,没有自己的名称,所以没法被pickle。对于模块top-level的函数和类的pickle,只会pickle其名称和定义函数和类的模块的名称,并不会pickle该函数或者类对应的值,对于实例,也只会pickle实例数据,比如类型名称和构造参数等内容,不会pickle其值,所以实际上在unpickle过程中,定义被pickle的函数和类的模块必须是可以import的,被导入之后,再根据unpickle后的函数和类的名称结合被导入的模块来重新构建对象。对于pickle更多详细的内容可以查看这里

       由于Windows下新建子进程的机制是利用了pickle的,所以在创建子进程时,目标函数和参数都必须是pickable的,不然会抛出一个PicklingError异常;此外,由于在Windows下,新建子进程还需要涉及到unpickle过程,而unpickle过程是需要导入定义函数和类的模块的,因此,在父进程中,创建新的子进程的语句必须放在if __name__=='__main__'语句后面,防止因为在unpickle过程中被import的过程中继续创建子进程,这会造成无穷的创建子进程,而在子进程中进一步创建子进程实际上也是multiprocessing不允许的,这就是为什么在Windows下,创建子进程的的主逻辑语句必须放在if __name__=='__main__'语句后面的原因。但是在Unix下,反序列化的过程不需要导入,从而可以不需要在__name__=='__main__'下写多进程,但是为了兼容,最好还是以兼容windows的方法创建进程,这总是一个好习惯。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值