多任务执行
- 定义:同一时间执行多个任务
- 执行方式
- 并发:单核交替时间执行
- 并行:多核同一时间点执行多个任务
进程
- 定义:OS资源分配的基本单位,默认一个程序至少一个进程,一个进程包含多个线程
1. 多个子进程
1.1 导入进程包
import multiprocessing
1.2 Process进程类的说明
Process([group [, target [, name [, args [, kwargs]]]]])
group:指定进程组,目前只能使用None
target:执行的目标任务名
name:进程名字
args:以元组方式给执行任务传参
kwargs:以字典方式给执行任务传参
Process
创建的实例对象的常用方法:
start():启动子进程实例(创建子进程)
join():等待子进程执行结束
terminate():不管任务是否完成,立即终止子进程
Process
创建的实例对象的常用属性:
name:当前进程的别名,默认为Process-N,N为从1开始递增的整数
1.3 代码示例
# 1. 导入进程包
import multiprocessing
import time
# 2. 创建功能函数
def dance():
for i in range(3):
print('danceing...')
time.sleep(0.2)
def sing():
for i in range(3):
print('singing...')
time.sleep(0.2)
#windows下必须要在__name__ == '__main__'中执行,否则报错,不断递归的拷贝调用子进程
if __name__ == '__main__':
# 3. 创建子进程(自己创建的进程都称为子进程)
# 1. group 暂为空,默认不写
# 2. target 指向函数
# 3. name 默认空则自动命名
dance_process = multiprocessing.Process(target = dance)
sing_process = multiprocessing.Process(target = sing)
# 4. 启动子进程
dance_process.start()
sing_process.start()
执行结果: 交替执行
danceing...
singing...
danceing...
singing...
danceing...
singing...
1.4 小结
- 导入进程包
- import multiprocessing
- 创建子进程
- sub_process = multiprocessing.Process(target=任务名)
- 启动子进程
- sub_process.start()
2. 获取进程编号
在函数内部获取,通过导包 import os
- 子进程ID:
os.getpid()
- 父进程ID:
os.getppid()
获取当前进程multiprocessing.current_process()
杀死进程 kill
3. 带有参数的任务函数
- 参数通过元祖传递
sub_process = multiprocessing.Process(target=任务名, arg=(name,))
- 参数通过字典传递
sub_process = multiprocessing.Process(target=任务名, kwarg={'name':'ahang', 'age':24})
- 代码示例
# 1. 导包
import multiprocessing
# 2. 创建含有参数的函数
def show_info(name, age):
for i in range(10):
print(f'{name}:age {age}')
# 3. 当在主模块内时:创建子进程
if __name__ == '__main__':
# 3.1 参数为元祖,元祖的顺序不可变化
# show_info_process = multiprocessing.Process(target=show_info, args=('zhang',24))
# 3.2 参数为字典,只需要关键字对应相同,与顺序无关
show_info_process = multiprocessing.Process(target=show_info, kwargs={'name':'zhang', 'age':'24'})
# 4. 开启进程
show_info_process.start()
4. 注意点
- 子进程之间不共享公共变量
- window下每个子进程会拷贝一份主进程的资源(变量、函数),所以每个子进程使用的变量都是局部的
- 防止创建子进程时循环递归,使用
if __name__ == __main__
判断是否为主模块 - 主进程需要等子进程结束后才结束
- 也可以提前销毁子进程
- 设置子进程为主进程的守护主进程,随着主进程结束销毁
- 在子进程开启前设置
子进程对象.daemon = True
- 在子进程开启前设置
- 主动结束子进程
- 在主进程结束时添加
子进程对象.terminate()
- 在主进程结束时添加
- 设置子进程为主进程的守护主进程,随着主进程结束销毁
- 也可以提前销毁子进程
- 代码示例
# 1. 设为守护主进程
show_info_process.daemon = True
show_info_process.start()
time.sleep(0.5)
print('over')
# 2. 主动结束子进程
show_info_process.terminate()