python——进程
1、进程概念与特征
1.1进程的概念
典型定义:
- 进程是程序的一次执行过程。
- 进程是一个程序及其数据在处理机上顺序执行时所发生的活动。
- 进程是具有独立功能的程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。
定义:
进程是进程实体的运行过程,是系统进行分配和调度的一个独立单位。
1.2进程的特征
- 动态性 :进程是程序的一次执行过程,具有一定的生命周期,是动态的产生、变化和消亡。进程最基本的特征。
- 并发性 :多个进程实体,同存于内存中,能在一段时间内同时运行。是进程的重要特征。引入进程的目的是为了使程序能与其他进程的程序并发执行,以提高资源利用率。
- 独立性 :进程实体是一个能独立运行、独立获得资源和独立接受调度的基本单位。凡未建立PCB的程序都不能作为一个独立的单位参与运行。
- 异步性 :进程按各自独立的、不可预知的速度前进,导致执行结果的不可再现性。
- 结构性:进程实体是由程序段、数据段和进程控制段三部分组成的。
2、多进程完成多任务
2.1 导入进程模块
#导入线程模块
import multiprocessing
2.2 Process进程类的语法结构如下:
Process([group [, target [, name [, args [, kwargs]]]]])
- group:指定进程组,目前只能使用None
- target:执行的目标任务名
- name:进程名字
- args:以元组方式给执行任务传参
- kwargs:以字典方式给执行任务传参
Process创建的实例对象的常用方法:
- start():启动子进程实例(创建子进程)
- join([timeout]):是否等待子进程执行结束,或等待多少秒
- terminate():不管任务是否完成,立即终止子进程
Process创建的实例对象的常用属性:
- name:当前进程的别名,默认为Process-N,N为从1开始递增的整数
- pid:当前进程的pid(进程号)
多进程完成多任务代码
import multiprocessing
import time
def run_proc():
"""子进程要执行的代码"""
while True:
print("----2----")
time.sleep(1)
if __name__ == '__main__':
# 创建子进程
sub_process = multiprocessing.Process(target=run_proc)
# 启动子进程
sub_process.start()
while True:
print("----1----")
time.sleep(1)
运行结果:
----1----
----2----
----1----
----2----
----1----
----2----
----1----
----2----
...... #无限循环
注意:由于进程之间的数据需要各自持有一份,所以创建进程需要的非常大的开销。
2.3 获取进程pid
import multiprocessing
import time
import os
def work():
# 查看当前进程
current_process = multiprocessing.current_process()
print("work:", current_process)
# 获取当前进程的编号
print("work进程编号:", current_process.pid, os.getpid())
# 获取父进程的编号
print("work父进程的编号:", os.getppid())
for i in range(10):
print("工作中....")
time.sleep(0.2)
# 扩展: 根据进程编号杀死对应的进程
os.kill(os.getpid(), 9)
if __name__ == '__main__':
# 查看当前进程
current_process = multiprocessing.current_process()
print("main:", current_process)
# 获取当前进程的编号
print("main进程的编号:", current_process.pid)
# 创建子进程
sub_process = multiprocessing.Process(target=work)
# 启动进程
sub_process.start()
# 主进程执行打印信息操作
for i in range(20):
print("我在主进程中执行...")
time.sleep(0.2)
运行结果:
main: <_MainProcess(MainProcess, started)>
main进程的编号: 14880
我在主进程中执行...
我在主进程中执行...
work: <Process(Process-1, started)>
work进程编号: 1968 1968
work父进程的编号: 14880
工作中....
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
我在主进程中执行...
进程已结束,退出代码0
2.4. 给子进程指定的函数传递参数
import multiprocessing
# 显示人员信息
def show_info(name, age):
print(name, age)
if __name__ == '__main__':
# 创建子进程
# 1. group:进程组,目前必须使用None,一般不用设置
# 2. target:执行目标函数
# 3. name: 进程名称
# 4. args: 以元组方式给函数传参
# 5. kwargs: 以字典方式给函数传参
sub_process = multiprocessing.Process(target=show_info, name="myprocess",
args=("古力娜扎", 18))
# 启动进程
sub_process.start()
# sub_process = multiprocessing.Process(target=show_info, name="myprocess",
# kwargs={"name": "貂蝉", "age": 20})
#
# # 启动进程
# sub_process.start()
运行结果:
古力娜扎 18
进程已结束,退出代码0
能够知道进程之间不共享全局变量
能够知道主进程会等待所有的子进程执行完成程序再退出
2.4.1进程之间不共享全局变量
import multiprocessing
import time
# 定义全局变量
my_list = list()
# 写入数据
def write_data():
for i in range(5):
my_list.append(i)
time.sleep(0.2)
print("write_data:", my_list)
# 读取数据
def read_data():
print(my_list)
if __name__ == '__main__':
# 创建写入数据的进程
write_process = multiprocessing.Process(target=write_data)
read_process = multiprocessing.Process(target=read_data)
write_process.start()
# 主进程等待写入进程执行完成以后代码 再继续往下执行
write_process.join()
read_process.start()
运行结果:
write_data: [0, 1, 2, 3, 4]
[]
进程已结束,退出代码0
注意:创建子进程其实是对主进程进行拷贝,进程之间相互独立,访问的全局变量不是同一个,所以进程之间不共享全局变量
2.4.2主进程会等待所有的子进程执行完成程序再退出
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()
# 让主进程等待1秒钟
time.sleep(1)
print("主进程执行完成了啦")
# 总结: 主进程会等待所有的子进程执行完成以后程序再退出
运行结果:
工作中...
工作中...
工作中...
工作中...
主进程执行完成了啦
工作中...
工作中...
工作中...
工作中...
工作中...
工作中...
进程已结束,退出代码0
销毁子进程的代码
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.daemon = True
work_process.start()
# 让主进程等待1秒钟
time.sleep(1)
print("主进程执行完成了啦")
# 让子进程直接销毁,表示终止执行, 主进程退出之前,把所有的子进程直接销毁就可以了
work_process.terminate()
# 总结: 主进程会等待所有的子进程执行完成以后程序再退出
运行结果:
工作中...
工作中...
工作中...
工作中...
主进程执行完成了啦
进程已结束,退出代码0
3、进程池
3.1进程池的概念
池子里面放的是进程,进程池会根据任务执行情况自动创建进程,而且尽量少创建进程,合理利用进程池中的进程完成多任务
当需要创建的子进程数量不多时,可以直接利用multiprocessing中的Process动态成生多个进程,但如果是上百甚至上千个目标,手动的去创建进程的工作量巨大,此时就可以用到multiprocessing模块提供的Pool方法。
初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会用之前的进程来执行新的任务.
进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。
进程池中有两个方法:
- apply
- apply_async
3.2. 进程池同步执行任务
进程池同步执行任务表示进程池中的进程在执行任务的时候一个执行完成另外一个才能执行,如果没有执行完会等待上一个进程执行
进程池同步实例代码
import multiprocessing
import time
# 拷贝任务
def work():
print("复制中...", multiprocessing.current_process().pid)
time.sleep(0.5)
if __name__ == '__main__':
# 创建进程池
# 3:进程池中进程的最大个数
pool = multiprocessing.Pool(3)
# 模拟大批量的任务,让进程池去执行
for i in range(5):
# 循环让进程池执行对应的work任务
# 同步执行任务,一个任务执行完成以后另外一个任务才能执行
pool.apply(work)
运行结果:
复制中... 3976
复制中... 5204
复制中... 7216
复制中... 3976
复制中... 5204
进程已结束,退出代码0
3.3. 进程池异步执行任务
进程池异步执行任务表示进程池中的进程同时执行任务,进程之间不会等待
进程池异步实例代码
# 进程池:池子里面放的进程,进程池会根据任务执行情况自动创建进程,而且尽量少创建进程,合理利用进程池中的进程完成多任务
import multiprocessing
import time
# 拷贝任务
def work():
print("复制中...", multiprocessing.current_process().pid)
# 获取当前进程的守护状态
# 提示:使用进程池创建的进程是守护主进程的状态,默认自己通过Process创建的进程是不是守住主进程的状态
# print(multiprocessing.current_process().daemon)
time.sleep(0.5)
if __name__ == '__main__':
# 创建进程池
# 3:进程池中进程的最大个数
pool = multiprocessing.Pool(3)
# 模拟大批量的任务,让进程池去执行
for i in range(5):
# 循环让进程池执行对应的work任务
# 同步执行任务,一个任务执行完成以后另外一个任务才能执行
# pool.apply(work)
# 异步执行,任务执行不会等待,多个任务一起执行
pool.apply_async(work)
# 关闭进程池,意思告诉主进程以后不会有新的任务添加进来
pool.close()
# 主进程等待进程池执行完成以后程序再退出
pool.join()
运行结果:
复制中... 13572
复制中... 3228
复制中... 1636
复制中... 13572
复制中... 3228
进程已结束,退出代码0
参考链接:
https://blog.csdn.net/hlg1995/article/details/81638732
https://www.cnblogs.com/wupeiqi/articles/5040827.html