$1 多进程概述
进程是正在执行中的应用程序,一个进程包含了该应用程序的所有信息,如加载数据内存空 间、代码、程序数据、对象句柄,执行单元等等,一个应用程序根据其功能的多样性,可以 通过多个进程并发的形式来实现。
计算机中多线程的操作已经可以实现多任务的处理机制了,但是如果涉及到多核 CPU 或者 多个 CPU 的硬件主机,多进程并发编程的实现能比多线程并发机制更加有效的利用和发挥 硬件资源优势。
$2 python多进程开发
2.1浅谈multiprocessing 模块
PYTHON 内建标准模块 multiprocessing 对多进程并发编程提供了良好的支持,通过该模块 的 Process 进程类型,可以很方便的创建和管理多个进程;通过该模块提供的 Lock|RLock进程锁类型、Event事件类型 、Condition 条件类型等等也可以很方便的完成进程间同步操作。
和多线程的操作方式类似,多进程的实现方式也提供了面向过程的实现和面向对象的实现 同时多进程的本地数据共享和通信模式也非常的类似多线程编程
multiprocess 常见属性和方法
名称 | 描述 |
---|---|
Process | 进程类型,用于创建和管理进程 |
Lock/RLock | 进程互斥锁/重用锁,用于进程同步 |
Event | 进程事件类型,用于进程同 |
Condition | 进程条件类型,用于进程同步 |
Queue | 进程队列类型,用于多进程数据共享 |
Manager | 进程管理类型,用于多进程数据共享 |
Listener/Client | 进程监听/客户端,基于网络多进程之间的数据共享 |
2.2 多进程的基础操作
通过多进程的方式进行操作,观察代码细节和运行模式
"""
version 1.1.0
author lkk
Email [email protected]
DESC python环境下的多进程
"""
import multiprocessing, os
def main_process():
# 打印信息 展示当前进程编号,父进程编号
print('你好,我是子进程,进程编号:{},父进程编号:{}'.format(os.getpid(), os.getppid()))
if __name__ =='__main__':
proc = multiprocessing.Process(target=main_process)
proc.start()
print('你好,我是主进程,进程编号:{},pycharm工具进程编号:{}'.format(os.getpid(), os.getppid()) )
运行程序,查看运行结果,通过进程编号就能看到主进程和创建的 进程之间的关系:
你好,我是主进程,进程编号:4228,pycharm工具进程编号:5432
你好,我是子进程,进程编号:9360,父进程编号:4228
从运行结果就能发现,main 方法运行的是主进程,通过 multiprocessing 创建的子进程是由 主进程产生的!其中5432 是 pycharm 工具进程->4228 当前程序进程->9360 子进程
2.4多进程面向对象实现
多进程的面向对象的实现方式类似多线程的操作模式 自定义进程类型,继承系统进程标准类型 multiprocessing.Process 重写父类的 run()方法,在方法中定义执行代码 在使用时创建该自定义进程类型的对象,调用对象的 start()方法启动一个新的进程
"""
version 1.1.0
author lkk
Email [email protected]
DESC python多进程面向对象
"""
import multiprocessing,os
class MyProcess(multiprocessing.Process):
"""自定义一个进程"""
def run(self):
"""对父类的进程处理方法进行重写"""
print('你好,我是子进程,进程编号:{},父进程编号:{}'.format(os.getpid(), os.getppid()))
if __name__ == '__main__':
print('你好,我是主进程,进程编号:{},pycharm工具进程编号:{}'.format(os.getpid(), os.getppid()))
"""创建并启动一个进程"""
My_proc = MyProcess()
My_proc.start()
你好,我是主进程,进程编号:11060,pycharm工具进程编号:5432
你好,我是子进程,进程编号:612,父进程编号:11060
看出两者的区别了么?
2.5带参数的多进程:共享?独占
多线程的操作模式下我们的全局变量是多个线程共享的,所以多线程并发模式下对于数据的 修改非常危险,那么多进程模式下数据的处理应该是什么样的呢?
通过两种方式来观察多进程模式下数据的处理
⚫ 全局变量的数据
⚫ 参数数据
(1) 全局变量:多进程数据处理
"""
version 1.1.0
author lkk
Email [email protected]
DESC python带参数的多进程
"""
import multiprocessing,time
msg = 3
def ch_numers():
"""定义处理函数,修改全局变量的值"""
global msg
while msg > 0:
msg -= 1
print(multiprocessing.current_process().name, '值改变了', msg)
if __name__ == '__main__':
"""创建两个进程,同时修改数据"""
for i in range(2):
p = multiprocessing.Process(target=ch_numers)
p.start()
time.sleep(2)
print(multiprocessing.current_process().name, msg)
运行结果截图
多进程程序执行过程中,如果出现对于当前文件全局变量的修改,出现如上结果是必然的;进程本身就是一个独立运行的程序,多进程意味着当前程序被执行了多次,每个进程中全局 变量的数据都是互相独立的。
(2) 参数传递:多进程数据处理
"""
version 1.1.0
author lkk
Email [email protected]
DESC 多进程数据处理
"""
import multiprocessing, time
def ch_numbers(msg):
"""定义处理函数,修改全局变量"""
while msg > 0:
msg -= 1
print(multiprocessing.current_process().name, '值发生改变了', msg)
if __name__ == '__main__':
# 创建两个进程,同时修改数据
msg = 3
for i in range(2):
p = multiprocessing.Process(target=ch_numbers, args=(msg,))
p.start()
time.sleep(2)
print(multiprocessing.current_process().name, msg)
上述程序中,我们将数据存储在变量 msg 中,通过参数的方式传递给进程函数进行执行 执行结果如下:
运行结果截图
给多进程并发处理函数传递参数的方式,并不能让数据可以被多个进程共享 函数执行并发操作时,每个进程都会单独拷贝一份当前进程的变量数据进行独立使用而不互 相影响,这也是出现上述代码结果的原因 。
2.6多个进程通信:multiprocessing.Manager
不同线程之间的数据通信,涉及到核心的数据共享问题,主要由 PYTHON 中提供的内建模 块 multiprocessing.Manager 类型实现,该类型内置了大量的用于数据共享的操作
multiprocessing.Manager 常见属性和方法
2.7 多个进程通信:multiprocessing.Queue
多个进程之间的通信操作,数据的传递在 PYTHON 中的 multiprocessing 模块中提供了一个 专门用于多进程之间进行数据传递的队列:Queue
multiprocessing.Queue 常见属性和方法
2.8多个进程通信:multiprocessing.Pipe
PYTHON 为了更加友好的多个进程之间的数据通信操作,提供了一个管道类型专门用于进程之间的协作:multiprocessing.Pipe
multiprocessing.Pipe 常见属性和方法
名称 | 描述 |
---|---|
init(duplex=True) | 初始化方法,返回两个数据 conn1,conn2 分别表示管道的两端,默认是双向通信 如果 duplex=False conn1 只能接受消息,conn2 只能发送消息 |
send(data) | 发送消息 |
recv() | 接受消息 |