进程
进程号是进程的唯一标识
查看方式:
1.在终端查看 tasklist
2.在本文件查看
查看子进程 : os.getpid()
查看父进程 : os.geippid()
tasklist| findstr python 在终端输入,只查看python解释器中的进程
创建进程的两种方式
1.常用
from multiprocessing import Process a = 1 b = 2 def task(n): print('%s is running'%n) #windows环境下想开启子进程一定要在 __name__ == '__main__'下 if __name__ == '__main__': # p = Process(target=task,args=(1,)) #p就是一个进程对象 通过args传参,必须是元祖形式 p = Process(target=task,kwargs={'n':1}) #也可以通过kwargs传参,字典形式 p.start() #给操作系统发送一个请求 print('主进程')
2.利用创建好的框架去构建进程 好处是很多方法和功能都提供好了,方便快捷,弊端是只能按照规定去写
from multiprocessing import Process class MyProcess(Process): def __init__(self,n): super().__init__() self.n = n def run(self): a = 1 b = 2 print('%s is running' % self.n) if __name__ == '__main__': p = MyProcess('alex') p.start() print('主进程')
验证进程间的内存隔离
from multiprocessing import Process import time x = 1000 def task(): time.sleep(3) global x x = 2 print('子进程:',x) if __name__ == '__main__': p = Process(target=task,) p.start() time.sleep(5) #先打印子进程,在打印主进程,看结果x是否被子进程修改 print('主进程:',x) 结果: 子进程: 2 主进程: 1000
主进程在子进程结束后再运行 join方法
from multiprocessing import Process import time x = 1000 def task(n): print('%s is begin'%n) time.sleep(3) print('%s is over' % n) def main(): print('主程序执行') if __name__ == '__main__': p = Process(target=task,args=(1,)) p.start() p.join() #通知p,子进程结束后,再执行主程序 main()
如果创建多个进程对象,发起请求之后,运行的顺序不固定
for循环实现:
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__': for i in range(1,11): p = Process(target=task,args=('p%s'%i,)) p.start() ''' 十个子进程请求几乎是同同时发起,谁先到达操作系统,操作系统给谁开辟空间,让cpu执行. ''' main()
for循环开启三个进程兑现,然后循环join三个子进程
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__': p_ls = [] start_time = time.time() for i in range(1,4): p = Process(target=task,args=('p%s'%i,)) p.start() p.join() p_ls.append(p) for p in p_ls: p.join() print(time.time() - start_time) main()
多个进程使用join,他们之间互不影响.
p.join() 会将除join方法以外的方法视为主进程的方法. 比如:p.start
进程对象的其他参数
name 为进程起一个别名
terminate 终止进程
is_alive 判断进程是否还存在
from multiprocessing import Process import time import os def task(n): print('%s is begin'%n) time.sleep(3) print('%s is over' % n) def main(): print('主程序执行') if __name__ == '__main__': p = Process(target=task,args=(1,),name='子进程') p.start() print(p.name) #为进程起别名 p.terminate() #杀死进程 time.sleep(2) p.join() #因为杀死进程和判断进程死活几乎是同时进行,判断可能在杀死进程之前执行,为确保杀死进程,睡一会或者使用join print(p.is_alive()) #判断进程死活 返回布尔值
在主进程和子进程中分别查看pid值
from multiprocessing import Process import time import os def task(n): print('%s is begin'%n) print('子进程:',os.getpid(),'主进程:',os.getppid()) time.sleep(3) print('%s is over' % n) def main(): print('主程序执行') if __name__ == '__main__': p = Process(target=task,args=(1,),name='子进程') p.start() print('子进程:', p.pid, '主进程:', os.getpid()) # 进程对象.pid也可以得到当前的pid值
僵尸进程与孤儿进程
(在linux系统才会出现)
理论上,各个进程的开启和结束互相不影响,不依赖
进程空间在内存中真正的消失才算是进程结束,主进程都是等着子进程结束之后才关闭
子进程是在主进程的基础上创建的,并且结束子进程的时间节点,主进程必须要知道
僵尸进程:死而不腐 主进程或者存在多个子进程时,代码结束时没有完全死掉,它们形成了僵尸进程,只会保存pid,退出状态和运行时间
主进程要获取僵尸进程保留的数据:
1.僵尸进程会占用一点空间,占用pid进程号,再想开启新进程的时候,可能会会出现因为没有进程号导致的开启不了
2.僵尸进程的回收是由主进程发起的
孤儿进程:主进程意外终止,剩下多个子进程就形成孤儿进程
在linux系统中,只要启动了子进程,内存中就会建立一个init主进程,是所有进程的主进程,最后的回收由init来执行
僵尸进程有害.僵尸进程的回收取决于主进程,如果主进程产生了大量的子进程,但是不着急回收这些僵尸进程,占用内存和pid号
孤儿进程无害.都会被init主进程回收
具体回收方法: waitpid()
守护进程
子进程守护主进程
子进程会等待主进程的代码结束之后就立即结束
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.start() time.sleep(2) # 子程序中的睡眠时间为3秒,当这时的两秒睡完之后,子程序不再执行,直接向下执行,调用main()函数 main()