1. 多进程
1.1 代码实现多进程的步骤:
| 详细步骤 | 代码实现 |
|---|---|
| 第一步:导包 | import multiprocessing |
| 第二步:创建进程对象,关联目标函数 | 进程名=multiprocessing.Process(target=目标函数名) 如果目标函数需要传参则传参,传参的两种方式: 方式一:args方式,接收所有的 位置参数(位置参数不能换位置):进程名=multiprocessing.Process(target=目标函数名, args=(参数1,参数2...) ); 方式二:kwargs方式,接收所有的 关键字参数(关键字参数可以换位置):进程名=multiprocessing.Process(target=目标函数名, kwargs={参数2:值2, 参数1,值1...} ); |
| 第三步:启动进程 | 进程名=multiprocessing.Process(target=目标函数名) |
进程的默认命名规则 是:Process-编号,编号是从1开始的;可通过name属性修改线程名:multiprocessing.Process(target=函数名, name='xx');如果不加name默认是1,从1开始;
代码演示:不带参任务和带参任务 :
(带参任务:函数在定义时有参数,创建进程对象关联目标函数时传参 args或 kwagrs;)
python
"""
案例:演示多进程 -- 不带参数任务(即任务函数不带参数)
实现步骤:
1.导包
2.创建进程对象,关联目标函数
3.启动进程
"""
# 1.导包
import multiprocessing
import time
# 2.定义函数,表示 编写代码
def coding():
for i in range(1,11):
time.sleep(0.1)#可以模拟耗时操作,更好的查看多任务的执行效果
print(f"正在敲第 {i} 遍代码...")
# 2.定义函数,表示 听音乐
def music():
for i in range(1,11):
time.sleep(0.1)
print(f"正在听第 {i} 遍音乐...")
# 一、单任务方式:顺序执行,上面的方法执行完才会执行下面的方法
# coding()
# music()
# 二、多任务方式:抢占CPU资源交替执行。通过main(主进程)来创建子进程:
# 3.创建两个进程对象,分别关联上述两个目标函数
if __name__ == '__main__':
# 进程p1关联coding函数,p1进程抢到CPU资源了就会执行这个函数
p1=multiprocessing.Process(target=coding)
p2=multiprocessing.Process(target=music)
# 4.启动进程:同一进程只能启动一次
p1.start()
p2.start()
python
"""
案例:演示多进程 -- 带参数任务(即任务函数带参数)
实现步骤:
1.导包
2.创建进程对象,关联目标函数
3.启动进程
进程传参有两种方式:
方式一:args方式,接收所有的 位置参数
方式二:kwargs方式,接收所有的 关键字参数
"""
# 需求:小明一边敲代码,一边听音乐
# 1.导包
import multiprocessing
import time
import os #用于测试获取进程id
# 2.定义函数,表示 敲代码
def coding(name, num):
for i in range(1, num+1):
time.sleep(0.1)#可以模拟耗时操作,更好的查看多任务的执行效果
print(f"{name} 正在敲第 {i} 行代码...")
print(f'p1进程的pid={os.getpid()},{multiprocessing.current_process().pid},父进程id={os.getppid()}')
# 2.定义函数,表示 听音乐
def music(name, count):
for i in range(1, count+1):
time.sleep(0.1)#可以模拟耗时操作,更好的查看多任务的执行效果
print(f"{name} 正在听第 {i} 首歌........")
print(f'p2进程的pid={os.getpid()},{multiprocessing.current_process().pid},父进程id={os.getppid()}')
# 3.创建两个进程对象,分别关联上述两个目标函数
if __name__ == '__main__':
# 进程p1关联coding函数,p1进程抢到CPU资源了就会执行这个函数
p1=multiprocessing.Process(target=coding, args=('小明', 10))#位置参数:两参数不能换位置
p2=multiprocessing.Process(target=music, kwargs={'count':20, 'name':'小王', })#关键字参数:两参数可以换位置
# 4.启动进程:同一进程只能启动一次
p1.start()
p2.start()
#查看主进程信息:
print(f'main进程的pid={os.getpid()},{multiprocessing.current_process().pid},父进程id={os.getppid()}')
1.2 获取进程 id:
main中创建的进程,如果没有特殊指定,它的父进程都是main 进程;
而main进程的父进程是 PyCharm 程序的pid;(任务管理器中可查看PyCharm软件的进程id)
代码如上;
| 操作 | 说明 |
|---|---|
| 获取当前进程id | 导入os包时:os.getpid() 导入multiprocessing包时:multiprocessing.current_process().pid |
| 获取父进程id | 导入os 包:os.getppid() |
1.3 进程的注意点:
① 进程之间不共享全局变量;
② 主进程会等待所有的子进程执行结束再结束: 若要设置主进程结束,子进程同步结束,两种方式:
方式一:设置子进程为守护进程:进程名.daemon=True;
方式二:强制关闭子进程:进程名.terminate();可能会导致子进程变成僵尸进程,交由python解释器自动回收(底层有init初始化进程来管理维护);

python
"""
案例:演示进程的特点--进程的数据隔离
进程的特点:
1.进程之间不共享全局变量(即进程之间的数据时相互隔离的):
因为子进程相当于父进程的副本,会将父进程'main外资源'拷贝一份
2.主进程会等待所有的子进程执行结束再结束
"""
# 需求:定义一个公共容器list=[],一个进程往里写数据,另一个进程读取数据
import multiprocessing
import time
# 1.定义一个公共容器
list=[]
# 2.定义函数,往容器中添加数据
def write_data():
for i in range(1, 4):
list.append(i)
print(f"添加数据:{i}")
# 到此添加完毕,打印即可
print(f'write_data函数:{list}')
# 3.定义函数,从容器中读取数据
def read_data():
time.sleep(3)
print(f'read_data:{list}')
print('我是main外函数,看我执行了几次---') #执行了三次
# 4.测试
if __name__ == '__main__':
# 5.创建两个进程对象,分别关联上述两个函数
p1=multiprocessing.Process(target=write_data)
p2=multiprocessing.Process(target=read_data)
# 6.启动进程
p1.start()
p2.start()
print('我是main函数,看我执行了几次') #执行了一次
# 运行结果:read_data休眠等到write_data执行添加完数据还是没读到数据,
# 说明进程间数据是隔离的
#我是main外函数,看我执行了几次 - --
#我是main函数,看我执行了几次
#我是main外函数,看我执行了几次 - --
#我是main外函数,看我执行了几次 - --
#添加数据:1
#添加数据:2
#添加数据:3
#write_data函数:[1, 2, 3]
#read_data:[]
python
"""
案例:演示进程的特点 --主进程会等待所有的子进程执行结束再结束
进程的特点:
1.进程之间不共享全局变量(即进程之间的数据时相互隔离的):
因为子进程相当于父进程的副本,会将父进程'main外资源'拷贝一份
2.主进程会等待所有的子进程执行结束再结束
"""
import multiprocessing
import time
# 1.定义函数,表示:子进程的目标函数
def work():
for i in range(3):
print(f"努力工作中。。。")
time.sleep(0.1)
# 2.测试
if __name__ == '__main__':
# 3.创建子进程对象,关联上述目标函数
# 进程的默认命名规则是:Process - 编号,编号是从1开始的;
p1=multiprocessing.Process(target=work, name='小王')
# 思路一:设置子进程为守护进程
# p1.daemon=True #加了这行代码(设置p1为守护进程),子进程结束后主进程立即结束
print(f'p1进程的名字:{p1.name}')
# 4.启动进程
p1.start()
# 5.主进程main休眠1秒后结束
time.sleep(1)
# 思路二:强制关闭子进程
p1.terminate() #加了这行代码(强制关闭p1进程),子进程结束后主进程立即结束
print('主进程结束')
# 运行结果:
# p1进程的名字:小王
# 努力工作中。。。
# 努力工作中。。。
# 努力工作中。。。
# 主进程结束