目录
- 进程对象属性
- 自定义进程类
- 进程池
- 管道通信
- 消息队列通信
- 共享内存
1. 进程对象属性
Process 进程对象属性
p.start()
p.join() ......
p.is_alive() 判断进程的生命周期状态 返回 True 和 False
p.name 进程名称 默认为 Process-1
p.pid 进程的PID号
p.daemon 默认False 此时主进程退出不会影响子进程执行
如果设置为True 则子进程会随着主进程结束而结束
注 : 要在start前设置 , 一般不和join一起使用
from multiprocessing import Process
from time import sleep
#带参数的进程函数
def worker(sec,name):
for i in range(3):
sleep(sec)
print("I'm %s"%name)
print("I'm working")
p = Process(target = worker,args = (2,),
kwargs = {"name":"Linux"},name = "worker")
p.start()
print("process name",p.name)
print("process pid: ",p.pid)
print("process is alive",p.is_alive())
p.join()
#daemon.py
from multiprocessing import Process
from time import sleep,ctime
def tm():
while True:
sleep(2)
print(ctime())
p = Process(target = tm)
p.daemon = True
p.start()
sleep(5)
print("main process exit")
2. 自定义进程类
创建自定义进程类 :
1. 继承Process
2. 编写自己的 __init__ , 同时加载父类的__init__方法
3. 重写 run 方法,可以通过生成的对象调用start自动运行
from multiprocessing import Process
import time
class ClockProcess(Process):
"""docstring for ClassName"""
def __init__(self, value):
self.value = value
super().__init__()
#重写run方法
def run(self):
for i in range(5):
print("the time is {}".format(time.ctime()))
time.sleep(self.value)
#创建自定义进程类的对象
p = ClockProcess(2)
#自动调用run
p.start()
p.join()
3. 进程池
多进程 :
优点 : 可以使用计算机多核,进行任务的并发进行,提高执行效率
空间独立,数据安全,运行不受其他进程影响,创建方便
缺点 : 进程的创建和删除消耗的系统资源较多
>>> 进程池技术
产生原因 : 如果有大量的任务需要多进程完成,则可能需要频繁创建删除进程
给计算机带来较多的资源消耗
原理 : 创建适当的进程放入进程池,用来处理待处理事件
处理完毕后进程不销毁,仍然在进程池中等待处理其他事件
进程的复用降低了资源的消耗
使用方法:
1.创建进程池,在池内放入适当的进程
2.将时间加入到进程池等待队列
3.事件不断取进程执行事件,直到所有事件执行完毕
4.关闭进程池,回收进程
from multiprocessing import Pool
Pool(processes)
功能 : 创建进程池对象
参数 : 进程池中有多少进程
pool.apply_async(func,arg,kwds) #常用,异步方式
功能 : 将事件放入到进程池队列
参数 : func 事件函数
args 以元组形式给 func 传参
kwds 以字典形式给func 传参
返回值 : 返回一个代表进程池时间的对象
作用 :
pool.apply(func,arg,kwds) #顺序执行
功能 : 将事件放入到进程池队列
参数 : func 事件函数
args 以元组形式给 func 传参
kwds 以字典形式给func 传参
返回值 : 无
pool.map(func,iterable)
功能 :参考内建map()函数
将要做的事件放入进程池
参数 : func 要执行的函数 iterable 可迭代对象
返回值 : 返回事件函数的返回值列表
pool.close() #close()放在join()前,先关闭再回收
功能 : 关闭进程池
pool.join()
功能 : 回收进程池
#pool.py
from multiprocessing import Pool
from time import sleep,ctime
def worker(msg):
sleep(2)
print(msg)
return(ctime())
#创建进程池
pool = Pool(processes = 4)
result = []
for i in range(10):
msg = 'hello %d'%i
#将事件放入进程池队列,等待执行
r = pool.apply_async(func = worker,args =(msg,))
result.append(r)
pool.close()
pool.join()
for i in result :
print(i.get()) #i.get() 获取函数对象返回值
#pool_map.py
from multiprocessing import Pool
import time
def fun(n):
time.sleep(1)
print("执行pool map事件")
return n**2
pool = Pool(processes = 4)
#use pool.map()
r = pool.map(fun,range(10))
pool.close()
pool.join()
print(r)
4. 管道通信
进程间通信(IPC) :
原因 : 进程空间相对独立,资源无法相互获取
此时在不同进程间通信间通信需要专门方法
通信方法: 管道 ; 消息队列 ; 共享内存 ; 信号 ; 信号量 ; 套接字
管道 Pipe :
通信原理 : 在内存中开辟管道空间,生成管道操作对象
多个进程使用"同一个"管道对象进行操作,即可实现通信
multiprocessing ---> Pipe
fd1 , fd2 = Pipe(duplex = True)
功能 : 创建管道
参数 : duplex 默认值为True 创建双向管道,False则为单向管道
返回值 : 表示管道的两端
如果是双向管道,两端都可以读写
如果是单向管道,则fd1制只读 , fd2只写
fd.recv()
功能 : 从管道读取信息
返回值 : 读取到的内容
*如果管道为空则阻塞
fd.send()
功能 : 向管道写入内容
参数 : 要写入的内容
*可以发送python数据类型
#pipe.py
from multiprocessing import Process,Pipe
import os,time
#创建管道对象
fd1,fd2 = Pipe()
def fun(name):
time.sleep(3)
#向管道内写入内容
fd1.send("hello"+str(name))
jobs = []
for i in range(5):
p = Process(target = fun ,args = (i,))
jobs.append(p)
p.start()
for i in range(5):
#读取管道
data = fd2.recv()
print(data)
for i in jobs:
i.join()
5. 消息队列通信
消息队列
队列 : 先进先出
通信原理 :在内存中建立队列数据结构模型
多个进程都可以通过队列存入内容
取出内容的顺序和存入顺序保持一致
创建队列 :
q = Queue(maxsize = 0)
功能 : 创建消息队列
参数 : 表示最多存放多少消息,默认表示根据内存分配存储
返回值 : 队列对象
q.put(data,[block,timeout])
功能:向队列存储消息
参数 : data 要存的内容
block 默认队列满时会阻塞,设置为False则非阻塞
timeout 超时时间
data = q.get([block,timeout])
功能 : 获取队列消息
参数 : block 默认队列空时会阻塞,设置为False则非阻塞
timeout 超时时间
返回值 : 返回取出的内容
q.full() #判断队列是否为满
q.empty() #判断队列是否为空
q.qsize() #判断队列中消息数量
q.close() #关闭队列
#通过消息队列实现进程间的通信
from multiprocessing import Process,Queue
import time
#创建消息队列
q = Queue()
def fun1():
time.sleep(1)
q.put({'a':1,'b':2})
def fun2():
time.sleep(2)
print("recv meg: ",q.get())
p1 = Process(target = fun1)
p2 = Process(target = fun2)
p1.start()
p2.start()
p1.join()
p2.join()
6. 共享内存
共享内存
通信原理:在内存空开辟一块空间,对多个进程可见
进程可以写入输入,但是每次写入的内容会覆盖之前的内容
obj = Value(ctype,obj)
功能 : 开辟共享内存空间
参数 : ctype 要存储的数据类型
常用 'i' 整型 'c' 字符串
obj 共享内存的初始化数据
返回 :共享内存对象
obj.value 即为共享内存值,对其修改即修改共享内存
obj = Array(ctype,obj)
功能 : 开辟共享内存空间
参数 : ctype 要存储的数据格式
obj 初始化存入的内容 比如列表,字符串 ('i',[1,2,3])
如果是整数则表示开辟空间的个数 ('i',3) >>> [ , , ]
返回值 : 返回共享内存对象
* 可以通过遍历过户每个元素的值
e.g. [1,2,3] ---> obj[1] == 2
* 如果存入的是字符串
obj.value 表示字符串的首地址
#value1.py(Value)
from multiprocessing import Process,Value
import time
import random
#创建共享内存
money = Value('i',2000)
#操作共享内存增加钱数
def deposite():
for i in range(100):
time.sleep(0.05)
#对value属性操作就是操作共享内存
money.value += random.randint(1,200)
#操作共享内存取钱
def withdraw():
for i in range(100):
time.sleep(0.04)
money.value -=random.randint(1,180)
p1 = Process(target = deposite)
p2 = Process(target = withdraw)
p1.start()
p2.start()
p1.join()
p2.join()
print(money.value)
#Array1.py (Array)
from multiprocessing import Array,Process
import time
#创建共享内存,初始放入列表
#shm = Array('i',[1,2,3,4,5])
#存入字符串
shm = Array('c',b'Hello')
def fun():
for i in shm:
print(i)
shm[0] = b'h'
p = Process(target = fun)
p.start()
p.join()
for i in shm:
print(i)
print(shm.value) #打印字符串 >>> 'hello'
总结
管道(Pipe) 消息队列(Queue) 共享内存(Value/Array)
开辟空间 内存 内存 内存
读写方式 两端读写 先进先出 覆盖之前内容
双向/单向
效率 一般 一般 较高
应用 多用于父 广泛灵活 需要注意
子进程 进行互斥操作
复习 :
1. 回顾进程间通信方法
2. 复习类的使用
3. 对进程使用和原理进行总结