获取进程及主进程的pid
什么是pid
进程在内存中开启多个,操作系统区分进程的方式就是通过每个进程都有的一个唯一的标识 — pid来区分
查看pid的方式
在终端查看当前所有进程的pid
在cmd窗口中输入tasklist
在终端查看正在执行的制定名字的进程的pid
在cmd窗口中输入tasklist|findstr + 进程名字
通过代码层面查看pid
os.getpid() 查看子进程
os.getppid() 查看父进程
验证进程间的空间隔离
from multiprocessing import Process import time x = 1000 def task(): global x x = 2 if __name__ == '__main__': p = Process(target=task) p.start() time.sleep(3) print(x)
join方法
join:等待,主进程等待子进程结束之后再执行
from multiprocessing import Process import time def task(name): time.sleep(1) print(f'{name} is running') if __name__ == '__main__': p = Process(target=task,args=('alex',)) p.start() p.join() # 告知主进程,p进程结束之后,主进程再运行 print('主进程执行') 开启多个子进程去验证: from multiprocessing import Process import time def task(name): time.sleep(1) print(f'{name} is running') if __name__ == '__main__': p1 = Process(target=task, args=('alex',)) p2 = Process(target=task, args=('barry',)) p3 = Process(target=task, args=('wusir',)) p1.start() p2.start() p3.start() # p1, p2, p3 三个子进程运行的先后顺序不定 # start只是通知一下操作系统,三个start几乎同一时刻发给操作系统 # 操作系统调用cpu先运行谁,谁先执行 print('主进程执行') from multiprocessing import Process import time def task(name,second): time.sleep(second) print(f'{name} is running') if __name__ == '__main__': p1 = Process(target=task, args=('alex', 1)) p2 = Process(target=task, args=('barry', 2)) p3 = Process(target=task, args=('wusir', 3)) start_time = time.time() p1.start() p2.start() p3.start() p1.join() # 视下面代码为主进程,此种写法为并发 p2.join() p3.join() print(f'主进程:{time.time() - start_time}之后,执行') from multiprocessing import Process import time def task(name,second): print(f'{name} is running') time.sleep(second) print(f'{name} is done') if __name__ == '__main__': p1 = Process(target=task, args=('alex', 1)) p2 = Process(target=task, args=('barry', 2)) p3 = Process(target=task, args=('wusir', 3)) start_time = time.time() p1.start() p1.join() #视下面代码为主进程,此种写法为串行 p2.start() p2.join() p3.start() p3.join() print(f'主进程:{time.time() - start_time}之后,执行')
进程对象的其他属性
from multiprocessing import Process import time def task(name): print(f'{name} is running') time.sleep(3) print(f'{name} is done') if __name__ == '__main__': p = Process(target=task,args=('怼哥',) ,name='任务1') # name给进程对象设置name属性 p.start() print(p.pid) # 获取进程pid号 print(p.name) time.sleep(1) p.terminate() # 终止(结束)子进程 # terminate 与 start一样的工作原理: 都是通知操作系统终止或者开启一个子进程,内存中终止或者开启(耗费时间) time.sleep(1) print(p.is_alive()) # 判断子进程是否存活 # 只是查看内存中p子进程是否运行. print('===主进程')
僵尸进程和孤儿进程
这是在Linux环境下才强调的两个概念,Windows环境下没有这两个概念
from multiprocessing import Process import time import os def task(name): print(f'{name} is running') print(f'子进程开始了:{os.getpid()}') time.sleep(50) if __name__ == '__main__': for i in range(100000): p = Process(target=task,args=('alex',)) p.start() print(f'主进程开始了:{os.getpid()}')
僵尸进程
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵尸进程。
僵尸进程的内存中只包括主进程的pid,子进程的开始时间,结束时间,至于主进程的代码以及文件,数据库等全部消失。可以利用waitpid()方法对僵尸进程进行“收尸”
僵尸进程是有害的。僵尸进程如果无限的开启子进程,子进程就会越来越多,占用内存
孤儿进程
如果一个主进程退出,而它的一或多个子进程还在运行,那么那些子进程将成为孤儿进程
孤儿进程是无害的,一段时间后,init会对孤儿进程进行回收
守护进程
运行在后台并且只在需要时才唤醒的进程称为守护进程(电子邮件,web网页,新闻,打印等)
主进程创建守护进程
守护进程会在主进程代码执行结束后就终止
守护进程内不能再开启子进程,否则就会抛出异常:AssertionError: daemonic processes are not allowed to have children
注意:进程之间是互相独立的,主进程代码运行结束,守护进程随即终止
#主进程代码运行完毕,守护进程就会结束 from multiprocessing import Process from threading import Thread import time def foo(): print(123) time.sleep(1) print("end123") def bar(): print(456) time.sleep(3) print("end456") p1=Process(target=foo) p2=Process(target=bar) p1.daemon=True #一定要在p.start()前设置,设置p为守护进程,禁止p创建子进程,并且父进程代码执行结束,p即终止运行 p1.start() p2.start() print("main-------") #打印该行则主进程代码结束,则守护进程p1应该被终止,可能会有p1任务执行的打印信息123,因为主进程打印main----时,p1也执行了,但是随即被终止