join()
import time from multiprocessing import Process x = 1 def task(name, num): print('%s is running' % name) global x x = 0 time.sleep(num) print('%s is done' % name) if __name__ == '__main__': obj_list = [] start_time = time.time() for i in range(1, 3): obj = Process(target=task, args=('子进程%s' % i, i)) obj_list.append(obj) obj.start() for obj in obj_list: obj.join() # join()让父进程原地等待,等子进程运行完毕后,才执行下一行代码(也拥有wait方法,等子进程运行完毕后,向操作系统发送请求,回收子进程占用的PID) end_start = time.time() print(x, end_start - start_time) # 可以看出修改子进程内的变量值并不会影响到父进程--->进程之间内存空间彼此隔离
一个例子
import time from multiprocessing import Process def task(name): print('%s is running'% name) time.sleep(15) # 给我们在cmd内查看进程预留时间 if __name__ == '__main__': p = Process(target=task,args=('进程一',)) p.start() print(p.pid) p.join() print(p.pid) # 执行结果 26324 进程一 is running 26324
说join()内也拥有wait()方法,会在子进程结束后向操作系统发送请求,回收子进程的pid,那么为什么在join()之后仍然能查到子进程的pid?
join()确实向操作系统发送了请求,操作系统也确实回收了子进程(通过cmd可以查看到),但是在子进程被创建时,pid已经成为父进程的一个属性(指向子进程的pid),join之后我们并没有删除这个属性(只是这个属性没有任何意义)
os.get_pid与os.get_ppid()
import time,os from multiprocessing import Process def task(name): print('%s is running'% name) print(os.getpid()) time.sleep(5) if __name__ == '__main__': p = Process(target=task,args=('进程一',)) p.start() p.join() print(os.getpid(),os.getppid()) time.sleep(100)
我们可以用os模块下的get_pid()查看当前进程的pid,以及get_ppid()查看父进程的pid
通过cmd可以看出子进程与父进程的pid都是指向python.exe,而父进程的父进程是pycharm
原因是子进程与父进程执行的都是python代码,需要通过解释器执行(将所要执行的代码作为参数传入解释器内),我们的进程是在pychram内执行的,如果通过cmd执行那么父进程就是cmd.exe
我们通过cmd执行这个py文件,然后用另一个cmd2去杀死cmd1,发现cmd1并没有关闭
原因是子进程在占用cmd的终端显示(cmd1确实被回收了,在cmd2内查不到cmd1的pid号),如果将子进程设置为后台运行,就会发现在我们杀死cmd1时,cmd1窗口就会立即关闭(进程与进程的内存空间彼此是隔离的)
obj.terminate():用于杀死子进程
obj.is_alive(): 判断一个子进程是否存活