多进程
重点源码
class Process():
name: str --------------name名字必须是字符串
daemon: bool
pid: Optional[int]
exitcode: Optional[int]
authkey: bytes
sentinel: int
易错
不同于深拷贝,进程的空间隔离,主进程和子进程中的不可变元素,除了数字地址是一样的,像字符串等的不遵循小数据池原理
1. 进程创建的两种方式
1. 第一种函数方式
from multiprocessing import Process
import time
def task(name): # 这个变量名可以改变,与下边对应即可
print(f"{name} is running")
time.sleep(2)
print(f"{name} is done")
if __name__ == "__main__":
#在Windows环境下,开启进程必须在__name__ == "__main__"下面
#此模块与windows某些地方有冲突
print(666)
p = Process(target=task,args=("太白",)) #args必须接受一个元祖
p.start()
# 只是向操作系统发出一个开辟子进程的信号,然后就执行下一行了,
# 将p这个进程放进去(copy主进程),然后让CPU去执行
#只复制了if条件语句的上边部分
print("==主")
- 注意
- task函数名可以改变,与下边对应即可
- Windows环境下,开启进程必须在测试端口下
- args传的值必须以元组形式,并且传的值要传的值一一对应
- p处只是提示操作系统开辟子进程,然后就继续执行了
- 子进程复制的只是if语句上边的内容
2. 第二种执行类方法
from multiprocessing import Process
import time
class MyProcess(Process): # 必须继承Process,类名可以换
def __init__(self,name):
super().__init__() #必须继承父类的__init__方法
#原因在于父类的init还封装着别的参数,必须继承
self.name = name
def run(self):
#必须要写成run方法,改了名字默认继承父类,pass,结果就只执行主进程
print(f"{self.name} is running")
time.sleep(2)
print(f"{self.name} is done")
if __name__ == "__main__":
p = MyProcess("太白")
p.start()
print("==主")
注意
- 此类必须继承Process
- 传值情况下必须继承父类的__init__方法
- 类方法必须是run,如果改了名字只会执行父类
- self.name 默认等于 MyProcess-1
- 必须继承父类的__init__方法,原因在于父类的init还封装着别的参数,必须继承
class MyProcess(Process): # 必须继承Process,类名可以换
def run(self):
# 必须要写成run方法,改了名字默认继承父类,pass,结果就只执行主进程
print(f"{self.name} is running")
time.sleep(2)
print(f"{self.name} is done") #默认继承父类的init方法
if __name__ == "__main__":
p = MyProcess()
p.start()
print("==主")
# 结果:
# ==主
# MyProcess-1 is running
# MyProcess-1 is done
2.进程的简单应用
1. 串行:所有的任务一个一个的完成(相当于调用三个函数)
from multiprocessing import Process
import time
def task(name):
print(f"{name} is running")
time.sleep(2)
print(f"{name} is done")
def task1(name):
print(f"{name} is running")
time.sleep(3)
print(f"{name} is done")
def task2(name):
print(f"{name} is running")
time.sleep(1)
print(f"{name} is done")
if __name__ == "__main__":
start_time = time.time()
task("太白")
task1("宝元")
task2("女神")
print(f"运行时间为:{time.time() - start_time}")
"""
太白 is running
太白 is done
宝元 is running
宝元 is done
女神 is running
女神 is done
运行时间为:6.001795053482056
"""
2. 并发:一个CPU完成多个任务,看起来像是同时完成
并行:多个CPU执行多个任务,真正的同时完成
from multiprocessing import Process
import time
def task(name):
print(f"{name} is running")
time.sleep(3)
print(f"{name} is done")
def task1(name):
print(f"{name} is running")
time.sleep(2)
print(f"{name} is done")
def task2(name):
print(f"{name} is running")
time.sleep(5)
print(f"{name} is done")
if __name__ == "__main__":
start_time = time.time()
p = Process(target=task,args=("太白",)) # 创建一个进程对象
p1 = Process(target=task1,args=("宝元",)) # 创建一个进程对象
p.start() #只提示创建就往下走了
p1.start() #
task2("女神") #第一个打印
print(f"运行时间为:{time.time() - start_time}")#必须等task2执行完
"""
女神 is running
太白 is running
宝元 is running
宝元 is done
太白 is done
女神 is done
运行时间为:5.075502872467041
"""
from multiprocessing import Process
import time
def task(name):
print(f"{name} is running")
time.sleep(3)
print(f"{name} is done")
def task1(name):
print(f"{name} is running")
time.sleep(1)
print(f"{name} is done")
def task2(name):
print(f"{name} is running")
time.sleep(2)
print(f"{name} is done")
if __name__ == "__main__":
start_time = time.time()
p = Process(target=task,args=("太白",)) # 创建一个进程对象
p1 = Process(target=task1,args=("宝元",)) # 创建一个进程对象
p2 = Process(target=task1,args=("女神",)) # 创建一个进程对象
p.start()
p1.start()
p2.start()
print(f"运行时间为:{time.time() - start_time}")
"""
运行时间为:0.12958216667175293
太白 is running
宝元 is running
女神 is running
宝元 is done
女神 is done
太白 is done
"""
![
3. pid是进程在内存中的唯一标识
在cmd终端输入tasklist查询所有进程的pid
在cmd终端输入tasklist|findstr python查询pycharm中多个进程的pid
在cmd终端输入tasklist|findstr pycharm查询主进程的pid
(在pycharm文件未关闭的前提下才可以找到)
具体操作如下
-
如何区分内存中的这些进程?
- cmd终端获取所有的进程的pid 方法 tasklist
-
代码级别如果获取一个进程pid
-
cmd终端获取所有子进程的pid 方法 tasklist|findstr python
-
![
-
![
-
import os import time print(f"子进程:{os.getpid()}") time.sleep(50) #关闭了在内存中就看不到了
-
cmd终端获取所有主进程的pid 方法 tasklist|findstr pycharm
-
![
![
import os import time print(f"主进程:{os.getppid()}") time.sleep(50) #关闭了在内存中就看不到了
from multiprocessing import Process import os def task(): print(f"子进程:{os.getpid()}") #子进程pid print(f"主进程:{os.getppid()}") #主进程pid if __name__ == "__main__": p = Process(target=task) p.start() print(f"==主进程{os.getpid()}") #进程pid
-
4. 验证进程之间的空间隔离
1. 主进程为不可变数据类型 : 主不变(空间隔离了,没有关系了)
子进程只是初始数据复制主进程的内容
from multiprocessing import Process
import time
name = "太白"
def task():
global name
name = "alexsb"
print(f"子进程:{name}")
if __name__ == "__main__":
p = Process(target=task)
p.start() #开辟一个子进程空间,
print(f"==主:{name}") #空间隔离,不会变
time.sleep(2)
print(f"==主:{name}") #空间隔离,不会变
2. 主进程为可变数据类型 : 主不变(空间隔离了,没有关系了)
子进程只是初始数据复制主进程的内容
from multiprocessing import Process
import time
lst = ["太白"]
def task():
lst.append("alexsb")
print(f"子进程:{lst}")
if __name__ == "__main__":
p = Process(target=task)
p.start() #开辟一个子进程空间,
print(f"==主:{lst}") #空间隔离,不会变
time.sleep(2)
print(f"==主:{lst}") #空间隔离,不会变
5. 进程的 join 阻塞 让主进程等待子进程结束之后,在执行主进程
(join后边的主进程内容被阻塞)
1. 一个子进程之间的主进程阻塞
from multiprocessing import Process
import time
def task(name):
print(f"{name} is running")
time.sleep(2)
print(f"{name} is gone")
if __name__ == "__main__":
start_time = time.time()
p = Process(target=task,args=("太白",)) #创建一个子进程对象
p.start()
p.join() #产生阻塞
print(f"==主:{time.time()-start_time}") #上边阻塞,要等待子进程执行完毕才执行
-
多个子进程之间的主进程阻塞
from multiprocessing import Process
import time
def task(name,sec):
print(f"{name} is running")
time.sleep(sec)
print(f"{name} is gone")
if __name__ == "__main__":
start_time = time.time()
p = Process(target=task,args=("太白",2))
p1 = Process(target=task,args=("宝元",3))
p2 = Process(target=task,args=("日天",1))
#以下三个几乎同时进行
p.start()
p1.start()
p2.start()
#多重阻塞
p.join()
print(f"==主1:{time.time() - start_time}")
p1.join()
print(f"==主2:{time.time() - start_time}")
p2.join()
print(f"==主3:{time.time() - start_time}")
"""
太白 is running
宝元 is running
日天 is running
日天 is gone
太白 is gone
==主1:2.1800968647003174
宝元 is gone
==主2:3.1918866634368896
==主3:3.1918866634368896
"""
3. 优化代码下列代码
from multiprocessing import Process
import time
def task(sec):
print(f'is running')
time.sleep(sec)
print(f' is gone')
if __name__ == '__main__':
start_time = time.time()
p1 = Process(target=task,args=(1,))
p2 = Process(target=task,args=(2,))
p3 = Process(target=task,args=(3,))
p1.start()
p2.start()
p3.start()
p1.join()
p2.join()
p3.join()
from multiprocessing import Process
import time
def task(sec):
print(f'is running')
time.sleep(sec)
print(f' is gone')
if __name__ == '__main__':
start_time = time.time()
lst = []
for i in range(1,4):
p = Process(target=task, args=(i,))
lst.append(p)
p.start()
for i in lst:
i.join()
print(f"==主:{time.time() - start_time}")
6.进程的其他参数
-
p.terminate() 杀死子进程(快速的话子进程不会执行)
from multiprocessing import Process
import time
def task(name):
print(f"{name} is going")
time.sleep(2)
print(f"{name} is done")
if __name__ == "__main__":
p = Process(target=task,args=("太白",))
p.start()
#time.sleep(1)
p.terminate() #杀死子进程,可以添加睡的时间选择让子进程执行一半时杀死
print("==主开始")
2. p.is_alive() 判断子进程是否还活着(True,False)
from multiprocessing import Process
import time
def task(name):
print(f"{name} is going")
time.sleep(2)
print(f"{name} is done")
if __name__ == "__main__":
p = Process(target=task,args=("太白",))
p.start()
p.terminate() #杀死子进程(需要点时间传递)
# p.join()
# time.sleep(1)
print(p.is_alive()) #上方如果不加阻塞代码,时间太短,结果是False
print("==主开始")
3. p.name() 给实例化对象封装name属性,默认为类名-1
p = Process(target=task,args=("太白",),name = "alex)
7. 守护进程 子进程守护着主进程,只要主进程结束,子进程跟着就结束
from multiprocessing import Process
import time
def task(name):
print(f"{name} is running")
time.sleep(2)
print(f"{name} is done")
if __name__ == "__main__":
p = Process(target=task,args=("太白",))
p.daemon = True #主进程结束,子进程就结束了
p.start()
# time.sleep(1)
# p.daemon = True # 一定要在子进程开启之前设置
print("==主")