2018-08-18
进程(Process):
计算机中正在进行的应用程序叫做进程。一个进程包含了该应用程序的所有信息,如加载数据内存空间、代码、程序数据、对象句柄、执行单元等等。
计算机中多线程的操作已经实现了多任务的处理机制了,但是多核CPU下的多进程并发编程的实现,能比多线程并发机制更加有效的利用和发挥硬件优势。
Python中的multiprocessing模块,可以实现多进程并发编程。
import multiprocessing #模块中常见的属性和方法
名称 作用
.Process # 进程类型用于创建、管理一个进程
.Lock/Rloak # 进程互斥锁/重用锁,用于进程同步
.Event # 进程事件类型,用于进程同步
.Condition # 进程条件类型,用于进程同步
.Queue # 进程队列类型,用于多进程数据共享
.Manager # 进程管理类型,多进程数据共享
.Listener|Client # 进程监听|客户端,基于网络多进程之间的数据共享
1、多进程的基本操作
1.1 创建一个面向过程的函数式进程
import multiprocessing, time, os
def hello_world():
# 输出信息, 展示当前进程编号, 父进程编号
print("hello myname is process", os.getpid(),os.getppid())
if __name__ == "__main__":
proc = multiprocessing.Process(target=hello_process) # 创建一个进程
proc.start() #启动进程
print("hello, i ma main:", os.getpid(), os.getppid())
运行程序,查看运行结果,通过进程编号就能看到主进程和创建的进程之间的关系:
hello , i am main : 2456 2772
hello my name is process 13536 2456
从运行结果就能发现,main 方法运行的是主进程,通过multiprocessing 创建的子进程是由主进程产生的!
其中 2772 是 pycharm 工具进程创建的程序主进程
->2456 当前程序进程
->13536 子进程
1.2 面向对象的面向对象编程-_-||
多进程的面向对象,的实现方式,类似多线程的操作模式
自定义进程类型:继承系统进程标准类型multiprocessing.Process
重写父类的run()方法,在方法中定义执行代码,run方法不用调用,会自动执行!!
在使用时创建自定义进程类型的对象,调用对象的start()方法启动一个新的进程
import multiprocessing, os
class My_process(multiprocessing.Process):
'''自定义一个进程类型'''
def run(self): # 重写run方法
print("hello, my name id process", os.getpid(), os.getppid())
if __name__ == "__main__":
print("hello, my name is main", os.,getpid(), os.getppid())
# 创建一个进程
my_proc = Myprocess()
#启动一个进程
my_proc.start()
执行结果,和函数式编程的结果相同:
hello, my name is main: 7048 2772
hello, my name is process: 3140 7048
- 多进程模式下的数据操作
(多线程的操作模式下,全局变量十多个线程共享的。所以多线程并发模式下对于数据的修改非常危险!)
多进程模式下,全局变量的参数是不共享的。在执行代码时,全局变量的值会被进程复制到进程自己的代码块里执行,全局变量的参数是不会变的!!
代码见下方:
import multiprocessing, time
# 定义全局变量
bl = 3
# 定义进程函数
def change_num():
global bl
while bl > 0:
bl -= 1
print(multiprocessing.Process().name, '进程里的全局变量:', bl)
if __name__ == "__main__":
# 创建两个进程,并修改数据
for i in range(2):
p = multiprocessing.Process(target = change_num)
p.start()
time.sleep(2)
print("这是全局变量", bl)
运行结果如下:
Process-1:1 进程里的全局变量: 2
Process-1:2 进程里的全局变量: 1
Process-1:3 进程里的全局变量: 0
Process-2:1 进程里的全局变量: 2
Process-2:2 进程里的全局变量: 1
Process-2:3 进程里的全局变量: 0
这是全局变量 3
可以发现进程里的全局变量的值虽然发生了变化,
但是外部全局变量的值没有改变!!
- 多进程的简化:内置进程池
通过进程池Pool,可以快速创建多个进程执行指定函数,完成馅饼发处理操作
Pool的属性和方法:
名称 作用
apply(func, args) #args-要传递参数, func-要执行的函数名称,同时阻塞当前进程知道该函数执行完成。
函数func只会在进程池中的一个进程池运行
---------------------------------------------------
#该方法不会形成阻塞
apply_async(func, args, callback, error_callback)
func (args-要传递参数, func-要执行的函数名称
args 函数执行完成之后可以通过结果对象的 get()方法获取结果 )
callback #如果结果对象可用时会自动调用 callback 指定的函数
error_callback #如果结果对象调用失败时会自动调用 error_callback 指定的函数
---------------------------------------------------
.close() #Pool 进程池的底层工作机制是向进程池提交任务产生工作进程执行
该方法是主动停止给进程池提交任务,并等待所有提交任务执行完成退出
.terminate() #立即结束该进程,当进程池对象被回收时自动调用该方法
.join() # 等待工作进程退出,再次之间必须调用 close()或者 teminate
实例如下:
import multiprocessing, time, os
def my_proc():
print(multiprocessing.current_process().name, "一个进程正在工作", os.getppid(), os.getpid())
time.sleep(1)
if __name__ == "__main__":
# 创建一个进程池
pool = multiprocessing.Pool(2)
# 循环任务
for i in range(20):
pool.apply_async(my_proc)
# 停止提交任务
pool.close()
# 独占执行
pool.join()
结果如下:
SpawnPoolWorker-1 一个进程正在工作 11596 14100
SpawnPoolWorker-2 一个进程正在工作 11596 13680
SpawnPoolWorker-1 一个进程正在工作 11596 14100
SpawnPoolWorker-2 一个进程正在工作 11596 13680
SpawnPoolWorker-2 一个进程正在工作 11596 13680
SpawnPoolWorker-1 一个进程正在工作 11596 14100
SpawnPoolWorker-1 一个进程正在工作 11596 14100
SpawnPoolWorker-2 一个进程正在工作 11596 13680
SpawnPoolWorker-2 一个进程正在工作 11596 13680
SpawnPoolWorker-1 一个进程正在工作 11596 14100
SpawnPoolWorker-2 一个进程正在工作 11596 13680
SpawnPoolWorker-1 一个进程正在工作 11596 14100
SpawnPoolWorker-2 一个进程正在工作 11596 13680
SpawnPoolWorker-1 一个进程正在工作 11596 14100
SpawnPoolWorker-2 一个进程正在工作 11596 13680
SpawnPoolWorker-1 一个进程正在工作 11596 14100
SpawnPoolWorker-2 一个进程正在工作 11596 13680
SpawnPoolWorker-1 一个进程正在工作 11596 14100
SpawnPoolWorker-2 一个进程正在工作 11596 13680
SpawnPoolWorker-1 一个进程正在工作 11596 14100
Process finished with exit code 0
可以发现进程池里的两个进程处理了循环的8个任务
- 多个进程通信,即数据实现共享(待实际操作)
Python中提供了multiprocessing.Manager类型,该类型内置了大量的用于实现数据共享的操作
常见的属性和方法:
名称 描述
Array 内置进程间共享 数组 类型
Queue 内置进程间共享 队列 类型
list() 内置进程间共享 列表 类型
dict() 内置进程间共享 字典 类型
value 内置进程间共享 值 类型