一.multiprocess模块
(1) 进程的创建--------process模块是一个创建进程的模块,借助这个模块,就可以完成进程的创建
Process([group [, target [, name [, args [, kwargs]]]]]),由该类实例化得到的对象,表示一个子进程中的任务(尚未启动) 强调: 1. 需要使用关键字的方式来指定参数 2. args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号
(2)进程的两种创建方式:
from multiprocessing import Process #进程创建方式1 #演示两种传参方式 def f1(n): print(n) if __name__ == '__main__': # p1 = Process(target=f1,args=('大力与奇迹',)) #创建进程对象 p1 = Process(target=f1,kwargs={'n':'大力'}) #创建进程对象 注意当传字典时,k值与f1(n)中的n保持一致 p1.start() #给操作系统发送了一个创建进程的信号,后续进程的创建都是操作系统的事儿了 #进程的创建方式2 class MyProcess(Process): def __init__(self,n): super().__init__() #别忘了执行父类的init self.n = n def run(self): print('宝宝and%s不可告人的事情'%self.n) if __name__ == '__main__': p1 = MyProcess('高望') p1.start()
(3)关于为什么写if __name__ == '__main__':
import time from multiprocessing import Process def f1(): time.sleep(3) print('xxxx') #windows系统下必须写main,因为windows系统创建子进程的方式决定的,开启一个子进程,这个子进程 会copy一份主进程的所有代码,并且机制类似于import引入,
这样就容易导致引入代码的时候,被引入的代码中的可执行程序被执行,导致递归开始进程,(内存会不断占用)会报错! 而写了main了以后,引用后,其名字时文件名,不是main,所以就不会执行主程序代码了!
而linus系统import不会执行代码,所以可以不写,只执行目标程序. if __name__ == '__main__': # p1 = Process(target=f1,) p1.start()
(4) 进程同步与异步任务执行时间对比(并发)
import time from multiprocessing import Process def f1(): time.sleep(3) print('xxxx') def f2(): time.sleep(3) print('ssss') if __name__ == '__main__': #f1() #f2() ##6s p1 = Process(target=f1,) p2 = Process(target=f2,) p1.start() p2.start() ##3s
(5) for循环创建进程:
import time from multiprocessing import Process def f1(i): time.sleep(3) print(i) if __name__ == '__main__': for i in range(20): p1 = Process(target=f1,args=(i,)) p1.start() #给操作系统发消息要创建进程,剩下的就不管了,由操作系统算法说了算.
代码很快执行完. for循环很快,20的对象创建进程执行任务的消息几乎同时发给操作系统,剩下的全部由操作系统说了算,操作系统分配空间创建进程和CPU内切换内存进行执行进程.20个创建好进程后,执行结果会发现,顺序不一致,顺序是乱的.原因是20个进程创建好处在就绪状态,操作系统切换内存,哪个先进程(21个进程,得包括主进程)由操作系统算法说了算,时间轮转,io操作等等,外界不知先执行哪个进程.因此不同的先后顺序!
(6) jion()
创建进程时,一般情况下,会出现,主进程代码很快执行完!如下:
import time from multiprocessing import Process def f1(): time.sleep(2) print('xxxx') def f2(): time.sleep(2) print('ssss') if __name__ == '__main__': p1 = Process(target=f1,) p2 = Process(target=f2,) print('我是主进程!!!')
打印结果: "我是主进程"
"xxxxxx"
"sssss"
但当遇到这样的情境: 当创建了子进程后,主进程需要等到子进程完成后才能进行下一步操作!这时就用到了jion().:
import time from multiprocessing import Process def f1(): time.sleep(2) print('xxxx') def f2(): time.sleep(2) print('ssss') if __name__ == '__main__': p1 = Process(target=f1,) p1.start() p1.join() # 主进程等待子进程p1运行完才继续执行 print('开始p2拉') p2 = Process(target=f2,) p2.start() p2.join() print('我要等了...等我的子进程...') # time.sleep(3) print('我是主进程!!!')
或者:
import time from multiprocessing import Process def f1(): time.sleep(2) print('xxxx') def f2(): time.sleep(2) print('ssss') # f1() # f2() if __name__ == '__main__': p1 = Process(target=f1,) p1.start() p2 = Process(target=f2,) p2.start() p1.join() # 主进程等待子进程运行完才继续执行 p2.join() print('我要等了...等我的子进程...') # time.sleep(3) print('我是主进程!!!')
二、 进程的其他方法
进程id;进程名字;查看进程是否活着;
如下:
import time
import os
from multiprocessing import Process
def f1():
print('子进程的pid',os.getpid())
print('子进程的父进程的pid',os.getppid()) #p = process;p= parents--->getppid
print('aaa')
def f2():
print('bbb')
if __name__ == '__main__':
p1 = Process(target=f1,name='宝宝1')
p2 = Process(target=f2,)
p1.start()
p2.start()
print(p1.name) 查看子进程的名字
print('子进程的pid',p1.pid)
print('父进程的id',os.getpid())
#进程的其他方法
def f1():
time.sleep(5)
print('子进程1号')
if __name__ == '__main__':
p = Process(target=f1,)
p.start()
print(p.is_alive()) #判断子进程是否还活着,是否还在运行
p.terminate() #给操作系统发送一个结束进程的信号
time.sleep(0.5)
print(p.is_alive()) #如果没有前面的time.sleep,该结果有可能是True,因为前面p.terminate()发送了结束信号,操作系统要对进程进行处理,
有个过程,把占用的内存空间和资源进行回收等,该进程还没结束,所以会可能是True;要注意的是python只能发送建立和结束进程的信号,没有能力去开辟建立和结束
进程的能力.平时口语说"开一个进程,执行某个任务",其实这个任务的执行过程才叫做进程.
三、验证进程之间是空间隔离的与守护进程
(1)验证进程之间是空间隔离的
验证进程之间是空间隔离
num=100
def f1():
global num
num = 3
print("子进程中的num",num)
if __name__ == '__main__':
p = Process(target=f1,)
p.start() #子进程会把程序import拷贝一遍
p.join() #等待子进程执行完,再执行主进程下一步
print("主进程中的num",num) #子进程中的num 3 主进程中的num 100 说明在子进程和主进程在不同的内存空间,无法改变
(2)守护进程 :主进程结束,守护子进程必须跟着结束---------------一直开着维护系统用的
# 守护进程,一直开着维护系统用的。
def f1():
time.sleep(1)
print("xxxx")
def f2():
time.sleep(5)
print("普通子进程的代码")
if __name__ == '__main__':
p = Process(target=f1,)
p.daemon = True #将该进程设置为守护进程,必须写在start之前,意思是如果我的主进程代码运行结束了,你这个子进程不管运行到什么地方,都直接结束
p.start()
#开启一个普通的子进程来验证一下守护进程的结束只和主进程的代码运行结束有关系,而整个程序的结束需要主进程和普通的子进程的代码都运行结束才结束。
p2 = Process(target=f2,)
p2.start()
# time.sleep(3)
#守护进程会跟着父进程的代码运行结束,就结束(这里涉及到一个谁快的问题,如果子程序在主进程完成结束前运行结束,)
注意:代码运行结束不代表程序执行结束 主进程结束了,普通子进程还没结束!!!
print("主进程结束")
(3)僵尸进程和孤儿进程(了解)
https://www.cnblogs.com/clschao/articles/9629392.html#part_8
四、进程锁(同步锁/互斥锁)(******重点)
五、进程队列(*****重点)
六、管道、进程的数据共享、信号量、事件