351-进程
复习导航:直接看最下面的踩坑记录
进程(Process)
1.进程(Process)是资源分配的最小单位(CPU、内存、硬盘)
进程是操作系统中资源分配的基本单位,每个进程都有独立的内存空间,进程之间不能直接访问彼此的内存空间。
一个软件至少有一个进程,资源分配的最小单元,一个软件可能会有多个进程
2.多进程是Python程序中实现多任务的一种方式,使用多进程可以大大提高程序的执行效率。
多进程的作用
多进程的作用是提高程序的执行效率,通过多进程可以同时执行多个任务,从而提高程序的执行效率。
单进程,单任务的执行
import time
def music():
for i in range(5):
print("播放音乐")
time.sleep(1)
def coding():
for i in range(5):
print("敲代码")
time.sleep(1)
if __name__ == "__main__":
music()
coding()
# 执行结果:
# 播放音乐
# 敲代码
# 播放音乐
# 敲代码
# 播放音乐
# 敲代码
多进程执行任务
程序运行会默认创建一个进程,这个默认创建的进程我们称之为主进程,程序运行后又创建了一个进程,我们称之为子进程。
创建步骤:
1.导入multiprocessing模块:import multiprocessing
2.通过进程类创建进程对象:p = multiprocessing.Process(target=task, name="子进程名称", args=(参数1, 参数2, ...))
参数:
- target:指定进程执行的任务,即函数名
- name:指定进程的名称,一般不用设置
- group:指定进程组,一般不用设置(目前只能使用None,因为还没有实现这个组)
- args:指定任务的参数,以元组的形式传入,元组方式传参一定要和参数的顺序保持一致。
- kwargs:指定任务的参数,以字典的形式传入,字典方式传参字典中的key一定要和参数名保持一致。
3.启动进程执行任务:p.start()
import multiprocessing
import time
def music():
for i in range(5):
print("播放音乐")
time.sleep(1)
def coding():
for i in range(5):
print("敲代码")
time.sleep(1)
if __name__ == "__main__":
# 在主进程中创建子进程
p1 = multiprocessing.Process(target=music, name="播放音乐")
p2 = multiprocessing.Process(target=coding, name="敲代码")
# 启动子进程
p1.start()
p2.start()
tip:print()要执行两个操作:输出信息和换行操作,当多任务执行太快的时候,print()来不及换行,就会导致信息混在一起。
多进程执行带参数的任务
import multiprocessing
import time
def music(n):
for i in range(n):
print("播放音乐")
time.sleep(1)
def coding(t):
for i in range(3):
print(f"敲代码{t}秒")
time.sleep(t)
if __name__ == "__main__":
p1 = multiprocessing.Process(target=music, args=(3,)) # 传入参数:(3,),元组
p2 = multiprocessing.Process(target=coding, args=(2,))
p1.start()
p2.start()
获取进程编号(PID)
1、进程编号的作用
当程序中进程的数量越来越多时,如果没有办法区分主进程和子进程还有不同的子进程,那么就无法
进行有效的进程管理,为了方便管理实际上每个进程都是有自己编号的。
2、两种进程编号
①获取当前进程编号:os.getpid()
②获取当前进程的父进程:os.getppid()
杀掉进程
os.kill(进程编号, 信号)
随着信号不同,功能不同;
- 9:强制杀死进程
- 15: 发送信号,正常杀死进程
注意:多进程之间无法共享全局变量
子进程创建后,会复制父进程的资源,子进程之间无法共享全局变量。
举例子:单任务中多个函数之间可以共享全局变量
import time
my_list = []
def write():
for i in range(5):
my_list.append(i)
time.sleep(0.1)
print(my_list)
def read():
print(my_list)
if __name__ == "__main__":
write()
time.sleep(1)
read()
# 执行结果:
# [0, 1, 2, 3, 4]
# [0, 1, 2, 3, 4]
多进程栗子:
import multiprocessing
import time
my_list = []
def write():
for i in range(5):
my_list.append(i)
time.sleep(0.1)
print(my_list)
def read():
print(my_list)
if __name__ == "__main__":
p1 = multiprocessing.Process(target=write)
p2 = multiprocessing.Process(target=read)
p1.start()
time.sleep(1)
p2.start()
# 执行结果:
# [0, 1, 2, 3, 4]
# []
当创建子进程的时候,全局变量会分别被复制一份独立存在,所以子进程之间无法共享全局变量。
注意:主进程与子进程的结束顺序
主进程默认会等待子进程执行结束以后再结束。
import multiprocessing
import time
def task():
for i in range(3):
print("任务执行中")
time.sleep(1)
if __name__ == "__main__":
p = multiprocessing.Process(target=task)
p.start()
time.sleep(1)
print("主进程执行结束")
# 执行结果:
# 任务执行中
# 主进程执行结束
# 任务执行中
# 任务执行中
进程代码执行结束后,整个程序并不会立即结束,而是等待子进程执行结束,当子进程执行结束后,整个主进程才能真正结束!
结论:主进程默认会等待子进程的结束而结束
关于设置主进程是否等待子进程执行完毕
- 主进程结束之前,等待子进程执行完毕:
p.join()
要实现主进程代码结束,子进程代码一起跟着结束的方法
设置守护进程
- 在start子进程之前设置
p1.daemon = True
:设置守护进程,主进程代码执行结束,子进程代码也会跟着结束。默认是False,表示主进程代码执行结束,子进程代码不会结束。
销毁子进程
- 主进程结束之前,强制销毁子进程:
p.terminate()
踩坑记录
在windows环境下面执行这个代码,无法正常运行:
from multiprocessing import Process
import time
# 定义在进程创建之前
def task():
for i in range(4):
print(i)
time.sleep(1)
p = Process(target=task)
p.start()
会报错
原因:
在 Windows 系统上,运行这个代码会遇到问题,因为在 Windows 上,使用 multiprocessing
模块时需要在 if __name__ == '__main__':
保护下启动进程。这是因为 Windows 使用的是 spawn 方法来创建子进程,它需要知道如何导入模块。
jupyter里中使用 multiprocessing
时,可能会遇到输出不显示
在 Jupyter Notebook 中使用 multiprocessing
时,可能会遇到输出不显示的问题。这是因为 Jupyter 使用的是不同的进程管理方式,导致标准输出的捕获和显示不如在命令行中那样直接。
- 解决方法不知道