Python 多任务编程 - 多进程
文章目录
1.多任务介绍
1.1 概念
- 同一时间执行多个任务。
- 多任务的最大好处充分利用cpu资源,提高程序的执行效率。
1.2 多任务的两种表现形式
- 并发
- 并行
1.3 并发
- 在一段时间内交替去执行多个任务。
- eg: 对于单核CPU处理多任务,操作系统轮流让各个任务交替执行。
- 任务数量大于 CPU的核心数。
1.4 并行
- 在一段时间内真正同时一起执行多个任务。
- eg: 对于多核CPU处理多任务,操作系统会给CPU的每个内核安排一个执行的任务,多个内核是真正一起同时执行多任务,在这里需要注意多核CPU是并行的执行多任务,始终有多个任务一起执行。
- 任务数量小于或等于 CPU的核心数。
2.进程的介绍
2.1 程序实现多任务的方式
- 在Python中想要实现多任务,可以使用多进程来完成。
2.2 进程的概念
- 进程(process)是资源分配的最小单位,它是操作系统进行资源分配和调度运行的基本单位,通俗理解,一个正在运行的程序就是一个进程,例如,正在运行的QQ微信他们都会进程。
- 注意:一个程序运行后至少有一个进程。
2.3 多进程的作用
def func_a():
print("任务A")
def func_b():
print("任务B")
func_a()
func_b()
3.多进程完成多任务
3.1 进程的创建步骤
- 导入进程包:
import multiprocessing
- 通过进程类创建进程对象
进程对象 = multiprocessing.Process()
- 启动进程执行任务
进程对象.start()
3.2 通过进程类创建进程对象
进程对象 = multiprocessing.Process(target=任务名)
参数名 | 说明 |
---|---|
target | 执行的任务名,这里指的是函数名(方法名) |
name | 进程名,一般不用设置 |
group | 进程组,目前只能用None |
3.3 进程创建与启动的代码
import time
# 唱歌
def sing():
for i in range(3):
print("唱歌...")
time.sleep(0.5)
# 跳舞
def dance():
for i in range(3):
print("跳舞...")
time.sleep(0.5)
if __name__ = '__main__':
sing()
dance()
# 1. 导入进程包
# 2. 使用进程类创建进程对象
# 3. 使用进程对象启动进程执行指定任务
import multiprocessing
import time
# 唱歌
def sing():
for i in range(3):
print("唱歌...")
time.sleep(0.5)
# 跳舞
def dance():
for i in range(3):
print("跳舞...")
time.sleep(0.5)
if __name__ = '__main__':
# target:指定进程执行的函数名
# 创建子进程
sing_process = multiprocessing.Process(target=sing)
# 创建子进程
dance_process = multiprocessing.Process(target=dance)
# 启动进程
sing_process.start()
dance_process.start()
4.进程执行带有参数的任务
4.1 进程执行带有参数的任务
参数名 | 说明 |
---|---|
arg | 以元组的方式给执行的任务传参 |
kwargs | 以字典的方式给任务传参 |
4.2 args参数的使用
# target: 进程执行的函数名
# args: 表示以元组的方式给函数传参
sing_process = multiprocessing.Process(target=sing,args=(3,))
sing_process.start()
4.3 kwargs参数的使用
dance_process = multiprocessing.Process(target=dance, kwargs={"num": 3})
dance_process.start()
import multiprocessing
import time
# 唱歌
def sing(num, name):
for i in range(num):
print(name)
print("唱歌...")
time.sleep(0.5)
# 跳舞
def dance(num, name):
for i in range(num):
print(name)
print("跳舞...")
time.sleep(0.5)
if __name__ = '__main__':
# target:指定进程执行的函数名
# 创建子进程
# args: 使用元组方式给指定任务传参
# 元组的元素顺序就是任务的参数顺序
sing_process = multiprocessing.Process(target=sing, args=(3, "xiaoming"))
# 创建子进程
# kwargs:使用字典方式传参
# key名就是参数的名字
dance_process = multiprocessing.Process(target=dance, kwargs={"name": "xiaohong", "num": 2})
# 启动进程
sing_process.start()
dance_process.start()
[注]:
- 元组方式传参:元组方式传参一定要和参数顺序保持一致。
- 字典方式传参:字典方式传参字典中的key一定要和参数名保持一致。
5.获取进程的编号
- 进程编号的作用: 当程序中的进程越来越多时,如果没办法区分主进程和子进程还有不同的子进程,那么就无法进行有效的进程管理,为了方便管理实际上每个进程都是有自己的编号的。
- 获取进程编号的两种方式:
- 获取当前进程编号
os.getpid()
- 获取当前父进程编号
os.getppid()
5.1 os.getpid()的使用
import os
pid = os.getpid()
print(pid)
5.2 os.getppid()的使用
def work():
# 获取当前进程的编号
print("work进程编号:", os.getpid())
# 获取父进程的编号
print("work父进程编号:", os.getppid())
[eg]
import multiprocessing
import time
import os
# 唱歌
def sing():
print("唱歌进程的pid:",os.getpid())
print("唱歌父进程的pid:",os.getppid())
for i in range(3):
print("唱歌...")
time.sleep(0.5)
# 跳舞
def dance():
print("跳舞进程的pid:", os.getpid())
print("跳舞父进程的pid:",os.getppid())
for i in range(3):
print("跳舞...")
time.sleep(0.5)
if __name__ = '__main__':
print("主进程的pid:",os.getpid())
# target:指定进程执行的函数名
# 创建子进程
sing_process = multiprocessing.Process(target=sing)
# 创建子进程
dance_process = multiprocessing.Process(target=dance)
# 启动进程
sing_process.start()
dance_process.start()
6.进程的注意点
6.1 主进程会等待所有的子进程执行结束后再结束
import multiprocessing
import time
def work():
for i in range(10):
print("工作中…")
time.sleep(0.2)
if __name__ = "__main__":
work_process = multiprocessing.Process(target=work)
work_process.start()
time.sleep(1)
print("主进程结束")
6.2 设置守护主进程
import multiprocessing
import timedef work():
for i in range(10):
print("工作中…")
time.sleep(0.2)
if __name__ = "__main__":
work_process=multiprocessing.Process(target=work)
# 设置守护主进程,主进程结束子进程自动销毁,不再执行子进程代码
work_process.daemon = True
work_process.start()
time.sleep(1)
print("主进程结束")
6.3 注意点
- 为了保证子进程能够正常运行,主进程会等所有子进程执行完成以后再销毁,设置守护主进程的目的是主进程退出子进程销毁,不再让主进程再等待子进程去执行。
- 设置守护主进程方式:
子进程对象.daemon = True