python MultiProcessing模块进程间通信的解惑与回顾

时间:2021-05-05 03:44:07

这段时间沉迷MultiProcessing模块不能自拔,没办法,python的基础不太熟,因此就是在不断地遇到问题解决问题。之前学习asyncio模块学的一知半解,后来想起MultiProcessing模块更是一知半解,趁着暑假无聊就研究了一下,不得不说,这加深了自己对Python基础的掌握与理解...于是就有了这一系列《python标准库之MultiProcessing库的研究 (1)》《python MultiProcessing标准库使用Queue通信的注意要点》《python标准库之MultiProcessing库的研究 (2)》,今天算是最后做个总结吧,以及解惑,随后你就知道解啥惑了。

我没有详细的讲解MultiProcessing这个包的源代码,没有讲解Pool底层机制,只有一个原因,我火候不够,若是现在强行理解,对我没多大好处,所以我选择顺其自然,先把最基本的用法掌握,实在不懂得看看源码,大概过一遍源码,对其实现机制有个大概的了解。MultiProcessing源代码包我大概就认真看了两个Pool.py以及managers.py,MultiProcessing的queues.py大概看了一下,最后总结的就是:不要觉得那些什么包,框架,模块高大上,多方便,其实认真阅读源码你就会发现,那其实就是某个基础扎实亦或是一群基础扎实的大牛写就得。换句话说,那些高大上的框架就是基础的东西组成的。有人说,你说的这么轻松,你写个试试。对不起,我写不了,我说这些不是我装逼怎么样,只是阐述事实,而且并没有贬低那些框架的意思,只是想降低你对这些框架的"敬畏"之心,不过话说回来,我觉着自己也能写就框架,只是现在还不是时候,基础不扎实。一个框架的写成,需要作者知识的深度与广度!可惜,我资历不够,慢慢来吧,我相信自己也会有那么一天...

总结的差不多了,具体的代码你可以看看上面提到的几篇文章

下面就是解惑了:为什么使用MultiProcessing的Process创建的进程就能够时候用MultiProcessing的Queue来实现进程间通信,而使用Pool进程池创建的进程却不行?而且为什么要使用MultiProcessing的Queue而不使用标准库的Queue。

我在之前的一篇文章说过,标准库的Queue只能实现线程间的通信,其get,put方法是阻塞的,而且除了这两个方法之外的其他方法是不安全的,不能保证在多线程通信时,能够稳定的访问变量,对变量进行处理...

Queue.Queue是进程内非阻塞队列,multiprocess.Queue是跨进程通信队列。多进程前者是各自私有,后者是各子进程共有。
from Queue import Queue这个是普通的队列模式,类似于普通列表,先进先出模式,get方法会阻塞请求,直到有数据get出来为止
from multiprocessing.Queue import Queue这个是多进程并发的Queue队列,用于解决多进程间的通信问题。普通Queue实现不了。例如来跑多进程对一批IP列表进行运算,运算后的结果都存到Queue队列里面,这个就必须使用multiprocessing提供的Queue来实现

线程是属于进程的,线程运行在进程空间内,同一进程所产生的线程共享同一内存空间,当进程退出时该进程所产生的线程都会被强制退出并清除。线程可与属于同一进程的其他线程共享进程所拥有的全部资源,但是其本身基本上不拥有系统资源,当然,拥有其在运行中必不可少的资源...进程间能不共享资源就不要共享...

so,解释的差不多了吧...

下面看看 官网 的对Manager的介绍:
Managers provide a way to create data which can be shared between different processes, including sharing over a network between processes running on different machines. A manager object controls a server process which manages shared objects. Other processes can access the shared objects by using proxies.

我看了下Manager的源代码,它使用了代理以及socket中的recv()等方法(好像是socket里面的)来实现跨进程通信以及代理通信

在这里要理清一个思绪:
MultiProcessing.Process创建的进程是有共同父进程的,而MultiProcess.Pool创建的进程则不是。进程池的存在就是为了减少进程的创建与销毁的开销。在这里我有个疑问了:创建一个子进程与创建一个进程有何区别?其开销应该不一样吧。
python实现多进程间通信的方式有很多种,例如队列,管道等.
但是这些方式只适用于多个进程都是源于同一个父进程的情况
如果多个进程不是源于同一个父进程,只能用共享内存,信号量等方式,但是这些方式对于复杂的数据结构,例如Queue,dict,list等,使用起来比较麻烦,不够灵活。
Manager是一种较为高级的多进程通信方式,它支持Python支持的任何数据结构....

因此,我们能够使用MultiProcessing的Queue通信,但是如果使用的是进程池创建的进程,那么就得使用Manager类封装的数据结构了...