1,对多进程的模块: multiprocess Process是进程的模块
form multiprocessing import Process从multiprocessing包中导入Process模块
- multiprocess是python中的一个操作管理进程的一个包,multi是取自multiple的多功能的意思,在这个包中,几乎包含了和进程操作的所有模块,有与子模块非常多,为了方便大家学习可以分为四个部分:创建进程部分,进程池部分,进程同步部分,进程之间数据共享
2,进程的并行与并发
- 2.1>并行:是指两者同时执行,好比有2条车道,在某一时间点(比如说下午3:58)两条车道上都有车在跑:(资源够用,比如三线程,四核CPU)
- 2.2.>并发:是指资源有限的情况下,两者交替轮流使用资源,比如只有一条车道(单核CPU资源),name就是A车先走,在某个时刻A车退出,把车道让给B车,B车走完,继续给A车使用
- 2.3>区别:
- 并行是从微观上,也就是在一个精确的时间片刻,有不同的成序在执行,这就要求必须要求有多个处理器
- 并发:是从微观上来看,在一个时间段上可以看出是通同时执行,比如一个服务器同时处理多个session
- 注意:早期单核CPU的时候,对于进程也是微观上串行(站在cpu角度看),宏观上是并行(站在人的角度有喝多程序在执行,那是因为CPU处理速度太快,你感受不到)
- 2.4>同步:一个人物的完成任务时,需要依赖另一个,只有等待另一个任务完成时,依赖的任务才能算完成,这时一种可靠的任务序列,要么成功都成功,失败都失败,两个任务的状态保持一致
- 2.5>异步:是不需要被等待的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即执行,只要自己完成了,整个任务就算完成了,至于被依赖的任务最终是否真正完成,依赖它 的任务无法完成,所以它是不可靠的任务序列
- 2.6>阻塞和非阻塞这两个概念与程序等待消息通知是的状态有关,也就是说阻塞与非阻塞主要是程序等待消息是的状态的角度来说的
就绪状态是在只要从新开始执行程序都会进入到就绪状态(阻塞的时候和启动程序的时候)
3,进程的开启:
- 3.1>使用函数来开启子进程
from multiprocessing import Process # 导入Process这个模块
import os # 导入os这个模块
import time # 导入时间模块
def func(n): # 定义一个函数
time.sleep(1) # 休眠1秒
print("执行到我了...我的pid值是:%s,我父进程(主进程)的pid的只是:%s" %(os.getpid(),os.getppid()))
# os.getpid()和os.getppid() # 是查找进程的pid值,每个运行的程序都会有一个独立的pid值,os.getppid()是获得父进程的pid值
if __name__ == "__main__": # 表示在windows系统当前模块的__name == __main__的时候执行以下代码
p = Process(target = func,args = (1,)) # Process其实是一个类,此时是实例化一个Process类的对象
p.start() # 是启动一个子进程(是通过python解释器发送给操作系统帮开一个子进程) 进程的就绪状态
time.sleep(2) # 休眠2秒,此时如果子进程和父进程休眠时间不一样,谁时间短就先执行谁,一样的话就没准了.
print("我是主进程...我自己的pid值是:%s,此时我的父进程的pid的值是:%s" % (os.getpid(),os.getppid()))
- 3.2>通过继承的方式来开启子进程
from multiprocessing import Process
class MyProcess(Process): # 自定义一个类名但是要继承Process类,因为Process里有_popen属性
def __init__(self):
super(MyProcess,self).__init__() # 调用父类的__init__方法
print("执行到这了...")
def run(self): # 定义一个run方法
print("这是以继承类的方式开启的子进程")
if __name__ == "__main__": # 同样的在windows操作系统中只有当模块中的条件满足执行以下带代码
p1 = MyProcess()# .实例化定义类的对象
p1.start() # 开启一个子进程(是通过python解释器去告诉操作系统帮开一个子进程) 就绪状态
p1.run() # 是直接干预操作系统进而直接先执行Process中的run方法开启一个子进程执行run方法
print("我是父进程...")
- 3.3>开启多个子进程
from multiprocessing import Process
def func(n):
print("这是子进程%s"%n)
if __name__ == "__main__":
for i in range(3): # for循环是去开启子进程的个数
p = Process(target=func,args =(i,)) # 此时的target = 后边跟的是上边的函数名,args=后边是for循环次数的参数
p.start()
print("这是父进程%s"%i)
- 3.4>通过集成的方式去开启多个子进程
class MyProcess(Process):
def __init__(self,count):
super(MyProcess, self).__init__()
self.count = count
def run(self):
print("这是子进程%s"%self.count)
if __name__ == "__main__":
for i in range(3):
p = MyProcess(i) # .实例化对象去传参数
p. start()
print("这里是父进程%s"%i)
4,进程的其他常用操作
- is_alive() # 判断子进程是否在执行返回的值是bool值(在开启子进程之后才能判断是否活着)
- terminate() # 杀死进程(杀死的是子进程)杀子进程需要一定的时间,网络传输就是有许多的不确定性
5,进程的start,和join
from multiprocessing import Process
import time
def func():
for i in range(10):
time.sleep(0.02)
print("儿子在这里")
if __name__ == "__main__":
p = Process(target=func)
p.start()
p.join() # 当join的时候就会把子进程运行完,再运行主进程(是异步变同步)主进程进行到到这就会阻塞
for i in range(5):
time.sleep(0.01)
print("爸爸在这里")
- 当进的时候有多个子进程,也会等子进程全部运行完再执行主进程的代码.
- p.join是让主进程等待子进程执行完,现象:主进程执行到这句话,主进程阻塞,等待子进程执行
- 父进程执行执行join,就会变成同步,不执行join,父进程和子进程就是异步的关系
- join()必须放在start()的后边
6,进程的长用属性
- 6.1>从主进程获得子进程的相关信息
from multiprocessing import Process
import os
def func():
print("这里是子进程,我自己的pid值是%s"%os.getpid())
if __name__ == "__main__":
p = Process(target=func)
p.start()
p.name = "liangxue" # 给当前这个子进程命名名字,当从新开启一个进程可以再重新命名
print("子进程的名字时%s"%p.name) # 查询这个名字
print("子进程是不是守护进程",p.daemon) # .False
- 6.2>守护进程(是在start(之前静实例化的对象设置为守护进程))
from multiprocessing import Process
import time
def func():
time.sleep(0.1)
print("我是子程,同时我也是守护进程")
if __name__ == "__main__":
p = Process(target = func)
p.daemon = True # 此时表示将开启的这个子进程设定为守护进程False是为正常进程,必须在开启子进程之前进行,将接下来的子进程变为守护进程.daemon的默认值是False
p.start()
time.sleep(0.5)
print("我这里是主进程")
守护进程的2个特点:
- 1>守护进程会随着父进程结束而结束
- 2>守护进程不能再创建子进程
7,多个子进程之间无法共享内存
from multiprocessing import Process
import time
import random
def func(i):
print("我是%s"%i)
if __name__ =="__main__":
l = [ ]
addr = ["河南的","山东","辽宁的","湖南的"]
for i in addr:
p = Process(target=func,args=(i,))
p.start()
l.append(p)
[p.join() for p in l] # 用列表推导式来同时join主四个子进程,目的就是等四个主进程都完毕了再执行主进程
time.sleep(1)
print("我选%s"%random.choice(addr)) # 等子进程都执行完毕后再执行主进程
- 每个子进程都是相对独立的个体,他们之间的资源不能共享.join不能再for循环里边,要放到一个列表中再用列表推导式,一次join主等4个子进程全部完事以后,在执行主程序的代码,效果是完全不一样的