multiprocess模块
仔细说来,multiprocess不是一个模块而是python中一个操作、管理进程的包。 之所以叫multi是取自multiple的多功能的意思,在这个包中几乎包含了和进程有关的所有子模块。由于提供的子模块非常多,为了方便大家归类记忆,我将这部分大致分为四个部分:创建进程部分,进程同步部分,进程池部分,进程之间数据共享。
进程的pid 父进程的ppid
import time import os a = 1 b = 2 print('子进程:',os.getpid()) #python解释器 print('父进程:',os.getppid()) #pycharm软件 time.sleep(20) print(a + b)
创建进程的两种方式
#方法一 #大多数都使用方法一创建一个子进程 from multiprocessing import Process def task(n): #task 固定写法 print("开始创建进程.............",n) #windows环境下想开启子进程一定要 __name__ == '__main__' if __name__ == '__main__': p = Process(target=task,args=(1,),kwargs={"n":1}) #task 固定写法,创建对象时"task"不能加"()",args表示位置参数的,kwargs表示关键字参数 p.start() #起动一个子进程
#方法2 class MyProcess(Process): #类的写法主要是直接继承"Process" 这个类. def __init__(self,n): super().__init__() #必须先要执行父类的 __init__属性,也就是"Process",要不然会报错 self.n = n def run(self): #子进程的代码全部都要写在这里面 a = 1 b = 2 print("%s is runing" % self.n) if __name__ == '__main__': p = MyProcess("alex") p.start() print("我是主")
验证进程间的内存隔离
from multiprocessing import Process import time x = 1000 def task(): time.sleep(2) global x x = 2 print("子进程:",x) if __name__ == '__main__': p = Process(target=task,) p.start() time.sleep(5) print("主:",x)
主进程在子程序运行完之后运行
from multiprocessing import Process def task(n): print("我是子进程开始运行了.......",n) time.sleep(5) print("子进程运行结束") if __name__ == '__main__': p = Process(target=task,args=(1,),name="子进程") #默认参数不变写法 args=(1,) 后面必须有逗号 name定义子进程的名字 p.start() p.join() #join 上面的子进程运行完毕之后运行主进程 print("我是主进程")
在一个主进程开启多个子进程
def task(n): print('%s is begin' % n) time.sleep(3) print('%s is over' % n) def main(): print('主进程执行.....') if __name__ == '__main__': p1 = Process(target=task,args=('p1',)) p2 = Process(target=task,args=('p2',)) p3 = Process(target=task,args=('p3',)) p1.start() # 发送一个请求 p2.start() # 发送一个请求 p3.start() # 发送一个请求 main()
for循环创建子进程
from multiprocessing import Process import time def task(n): print("%s 开始运行" % n) time.sleep(3) print("%s 运行结束了" % n) if __name__ == '__main__': for i in range(1,4): p = Process(target=task,args=("p%s" % i,)) p.start()
子进程和主进程的运行顺序"串行"和"并发"
串行消耗时间长,并发消耗时间短 ##串行## from multiprocessing import Process import time def task(n): print('%s is begin' % n) time.sleep(3) print('%s is over' % n) def main(): print('主进程执行.....') if __name__ == '__main__': # 创建三个进程对象 p1 = Process(target=task, args=('p1',)) p2 = Process(target=task, args=('p2',)) p3 = Process(target=task, args=('p3',)) start_time = time.time() # 发起三个请求 p1.start() p1.join() # 高速我的主进程,你要在我执行完毕之后在运行 # print(111) p2.start() p2.join() p3.start() p3.join() # # 如果你要按照上面的写法:串行. print(time.time() - start_time) main() ##并发## from multiprocessing import Process import time def task(n): print('%s is begin' % n) time.sleep(n) print('%s is over' % n) def main(): print('主进程执行.....') if __name__ == '__main__': # 创建三个进程对象 p1 = Process(target=task, args=(1,)) p2 = Process(target=task, args=(2,)) p3 = Process(target=task, args=(3,)) start_time = time.time() # 发起三个请求 p1.start() p2.start() p3.start() p1.join() # 1 p2.join() # 2 p3.join() # 3 print(time.time() - start_time) main()
for循环实现主程序等待等待所有子程序结束之后再运行
from multiprocessing import Process import time def task(n): print("%s开始运行" % n) # time.sleep(3) print("%s运行结束" % n) if __name__ == '__main__': lst = [] for i in range(1,4): p = Process(target=task,args=("p%s" % i,)) p.start() p.join() #这里使用join是为了让数字顺序拼接上"1,2,3","p1开始运行,p2开始运行,p3开始运行" lst.append(p) # 把子进程添加到列表内不让在外部执行,如果不添加到列表内在外执行之后就变成了串行. for c in lst: # 拿到列表内的子进程 c.join() #通过join执行下面的主程序 print("我是主程序") 总结: 1,多个进程使用join,他们之间互不影响. p.join() 会将除join方法以外的方法视为主进程的方法(视为串行). 比如:p.start
进程和对象的其他参数
from multiprocessing import Process import time import os def task(n): print('%s is begin' % n) # print(os.getpid()) print('子进程:', os.getpid(), '主:', os.getppid()) time.sleep(3) print('%s is over' % n) def main(): print('主进程执行.....') # if __name__ == '__main__': # p1 = Process(target=task, args=('p1',),name='紫禁城') # 自定制别名 # p2 = Process(target=task, args=('p2',)) # p1.start() # p2.start() # print(p1.name) # 为进程起别名 # print(p2.name) # p1.start() # 给操作系统发送请求 # p1.terminate() # 杀死进程 # # time.sleep(3) # # p1.join() # time.sleep(1) # print(p1.is_alive()) # 判断进程死活 # 判断id # p1 = Process(target=task,args=(1,)) # p1.start() # # print('子进程:',p1.pid) # 获取p1进程pid # print('子进程:',p1.pid,'主:',os.getpid())
僵尸进程和孤儿进程
僵尸进程一般针对linux系统,当一个主进程中的子进程在运行完毕之后,就会产生僵尸进程,但是liux底层有垃圾回收机制(waitpid,内核层面),会默认将僵尸进程回收,如果主进程产生了大量的子进程回收不及时可能会影响的系统性能.
僵尸进程:占有一点空间,保存pid,运行时间,状态,僵尸进程的回收是由主进程发起的.
孤儿进程:当你的主进程意外挂了,就会形成孤儿进程,孤儿进程就会交给linux系统来处理.
守护进程
守护进程会等待主进程的代码结束之后就立即结束
守护进程也是一个子进程,主进程永远要在子进程结束之后才能使用,因为主进程要负责回收子进程
from multiprocessing import Process import time def task(n): print('%s is begin' % n) time.sleep(3) print('%s is over' % n) def main(): print('主进程执行.....') if __name__ == '__main__': # 创建三个进程对象 p1 = Process(target=task, args=('p1',)) p1.daemon = True # 你的p1进程就设置成了守护进程,便不会再执行p1的内容了. p1.start() time.sleep(2) main()