通常使用multiprocessing 创建进程,父进程只用作进程的创建和回收,不做其他工作。
multiprocessing进程对象属性
p.start() | 启动进程 |
p.join() | 回收进程 |
p.is_slive() | 判断进程生命周期,返回True False |
p.name | 进程名称 默认为Process-1 如果起名字则为自定义名称 |
p.pid | 创建的进程的PID |
p.daemon | 默认值为False 父进程退出不会影响子进程运行 如果设置为True 则父进程退出子进程也会退出 |
*daemon的设置必须在start前 *如果设置daemon 为True 则不再使用 join |
创建自己的进程类
1、继承Process 类 |
2、重写__init_并且调用父类__init__ |
3、重写run方法,此时生成对象后,调用start就会自动运行run |
多进程
优点:能并行执行多个任务,提高效率
创建方便,运行独立,不受其他进程影响
数据安全
缺点:进程的创建和删除都需要消耗计算机的资源
进程池技术
产生原因 | 如果大量任务需要多进程完成,且可能需要频繁的创建和删除进程,给计算机带来大量的资源消耗 |
原理 | 在进程池内运行一定的数量进程,通过这些进程完成进程池队列的事件,直到事件执行完毕,减少进程不断的创建删除过程。 |
实施操作方法 | 1.创建进程池,在进程池中放入适当进程 |
2.将事件加入到进程池队列 | |
3.事件不断运行,直到所有事件运行完毕 | |
4.关闭进程池,回收进程 |
具体程序流程
from multiprocessing import Pool
Pool = Pool(processes)
功能: 创建进程池对象
参数: 表示进程池中有多少进程
pool.apply_async(func, args,kwds)
功能: 将事件方法进程池队列
参数: func 要执行的事件
args 给func用元组传参
kwds 给func用字典传参
返回值: 返回事件对象 通过get()方法获取事件函数返回值
pool.close()
功能 : 关闭进程池,不能再添加新的事件
pool.join()
功能: 阻塞等待回收进程池
pool.map(func,iter)
功能: 将要完成的事件放入进程池
参数: func 要完成的事件函数
iter 可迭代对象给func传参
返回值: 事件函数的返回值列表
进程间通信
进程间由于空间独立,资源无法互相直接获取,此时在不同的进程间进行数据传递就需要专门的通信方法 | ||
进程间通信方法(IPC) |
1.管道通信Pipe | 管道:在内存中开辟一段空间,形成管道结构,管道对多个进程可见,进程可以对管道进程读写操作 |
multiprocessing---à pipe fd1,fd2 = Pipe(duplex = True) 创建管道 | ||
功能: 创建一个管道 参数:默认为双向管道 如果设置为False 则为单向管道 返回值:如果是双向管道,fd1 fd2都可以进行读写操作。 如果是单向管道,fd1只可读,fd2只可写 | ||
fd.recv() 读 | ||
功能:从管道读取内容 返回值: 读到的内容 *如果管道无内容则阻塞 | ||
fd.send(data) 写 | ||
功能: 向管道写入内容 参数: 要发送的内容 *几乎可以发送所有python支持的数据 | ||
2.消息队列 | 队列: 先进先出 在内存中开辟队列结构空间,多个进程可以向队列投放消息,在取出的时候按存入顺序取出 | |
创建队列 q = Queue(maxsize = 0) 功能: 创建队列 参数: maxsize 默认表示根据系统分配空间存储信息如果传入一个正整数 则表示最多存放多少条消息 返回: 队列对象 | ||
存放消息 q.put(data,[block,timeout]) 功能: 存放消息 参数: data 存入的消息(python数据类型) block 默认为True 表示当队列满的时候阻塞设置为False 则表示非阻塞 timeout 当block为True表示超时时间 | ||
取出消息 Data = q.get([block,timeout]) 功能: 取出消息 参数: block 默认为True 当队列空时阻塞 设置为False表示非阻塞 timeout 当block为True 时表示超时时间 返回值: 返回获取的消息 q.full() 判断队列是否为满 q.empty() 判断队列是否为空 q.qsize() 判断当前队列有多少消息 q.close() 关闭队列 | ||
3.共享内存 | 在内存中开辟一段空间,存储数据,对多个进程可见。每次写入共享内存中的数据会覆盖之前的内容 | |
创建共享内存(1) from multiprocessing import Value | ||
开辟共享内存 obj = Value(ctype,obj) 功能: 开辟共享内存空间 参数: ctype 字符串 要转变为c 的数据类型 对比类型对照表 obj 共享内存的初始化数据 返回: 返回共享内存对象 obj.value 表示共享内存中的值,对其修改或者使用即可 | ||
创建共享内存(2) obj = Array(ctype,obj) 功能:开辟共享内存 参数:ctype 要转换的c的类型 obj 要存入共享的数据 列表 将列表存入共享内存,数据类型一致 正整数 表示开辟几个数据空间 | ||
4.信息 | 一个进程向另一个进程通过信号传递某种讯息,接收方在接收到信号后进行相应的处理 | |
查看信号的命令 kill –l kill –signum PID 给PID 的进程发送一个信息 | ||
关于信息(详见图片signal.png) 信号名称:信号的名字或者数字 信号含义:信号的作用 默认行为:当一个进程接收信号时采取的行为 终止进程,暂停进程,忽略产生 e.g SIGHUP 终端断开 SIGINT ctrl + c SIGQUIT ctrl + \ SIGTSTP ctrl + z SIGKILL 终止进程且不能被处理 SIGSTOP 暂停进程且不能被处理 SIGALRM 时钟信息 SIGCHLD 子进程状态改变发给父进程 | ||
通过python进行信号处理 示例见day03 /2.py 发送 os.kill(pid,sig) 功能:发送信息给某个进程 参数: pid 给哪个进程发送信息 sig 要发送什么信号 signal.alarm(sec) 功能:一定时间后给自身发送一个 SIGALRM信号 参数:指定时间 说明: 一个进程中只能设置 一个时钟,第二个时钟会覆盖之前的时间 程序执行的同步和异步 同步:按照步骤一步一步顺序执行 异步:在程序执行中利用内核,不影响应用层程序持续执行 *信号是唯一的异步通信方式*
signal.pause() 功能:阻塞等待一个信号的发送 接收处理 示例见 day03 Signal.signal(signum,handler) 功能: 处理信息 参数: sugnum :要处理的信息 handler:信号的处理方法
示例 day03 5.py
SIG_DFL 表示使用默认的方法处理 SIG_IGN 表示忽略这个信号 func 自定义函数处理信号 格式要求: def func(sig,frame): pass sig: 表示要处理的信息 frame: 信号的结构对象 说明: *signal 函数是一个异步处理函数 *signal 函数不能处理 SIGKILL STGSOP信号 *在父进程中使用 slignal(SIGCHLD,SIG_IGN),这样子进程退出会有系统自动处理 | ||
5.信号量 | 给定一定的数量,对多个进程可见,并且多个进程根据型号量的多少确定不同的行为 | |
multiprocessing -à semaphore() sem = semaphore(num) 示例:day03 6.py 功能:生成信号量对象 参数:信号量的初始化 返回值:信号量对象 sem.acquire() 信号量数量减一 信号量为0时会阻塞 sem.release() 信号量数量加一 sem.get_value() 获取当前信号量的值 | ||
6.套接字 |
| 管道 | 消息队列 | 共享内存 |
开辟空间 | 内存 | 内存 | 内存 |
读写方式 | 两端读写 双向/单向 | 先进先出 | 操作覆盖内存 |
效应 | 一般 | 一般 | 较快 |
应用 | 多用于两端通信 | 使用广泛 | 复杂,需要同步互斥机制 |