一·介绍
进程:实现多任务的一种方式。
一个正在运行的程序或软件就是一个进程,它是操作系统进行资源分配的基本单位,也就是说每启动一个进程,操作系统都会给其分配一定的运行资源(内存资源)保证进程的运行。
一个程序运行后至少有一个进程,一个进程默认有一个线程,进程里面可以创建多个线程,线程是依附在进程里面的,没有进程就没有线程
二·多进程的使用
1.导入进程包
import multiprcoessing
2.Process进程类说明
Process([group[,target[,name[,args[,kwargs]]]]])
group:指定进程组,目前只能使用None
target:执行的目标任务名
name:进程名字
args:以元祖方式给执行任务传参
kwargs:以字典方式给执行任务传参
Process创建的实例对象的常用方法:
start():启动子进程实例(创建子进程)
join:等待子进程执行结束
terminate():不管任务是否完成,立即终止子进程
os.getpid() 获取当前进程编号
os.getppid()获取当前父进程编号
进程是无序的,具体哪个进程先执行是由操作系统调度决定
import multiprocessing
import time
import os
def sing():
#获取当前进程(主进程)编号
main_process_id= os.getpid()
#获取当前进程对象,查看当前代码是由哪个进程执行的:multiprocessing.current_process()
print('main_process_id:', main_process_id,multiprocessing.current_process())
#获取当前的父进程编号
sing_process_parrnt_id = os.getppid()
print('sing_process_parrnt_id:',sing_process_parrnt_id)
for i in range(3):
print('sing...')
time.sleep(0.3)
def dance():
#获取当前进程(主进程)编号
main_process_id= os.getpid()
#获取当前进程对象,查看当前代码是由哪个进程执行的:multiprocessing.current_process()
print('main_process_id:', main_process_id,multiprocessing.current_process())
# 获取当前的父进程编号
dance_process_parrnt_id = os.getppid()
print('dance_process_parrnt_id:', dance_process_parrnt_id)
for i in range(3):
print('dance...')
time.sleep(0.5)
if __name__ == '__main__':
#创建子进程(自己手动创建的进程成为子进程,在__init__.py文件中已经导入的Preocess类 )
#group:进程组,一般不需要设置,为None
#target:进程执行的目标任务
#name:进程名,如果不设置,默认是Process-1
dance_process = multiprocessing.Process(target=dance,name='dance_process')
# print('dance_process:', dance_process)
#启动进程对应任务
dance_process.start()
#主进程进行任务
sing()
#运行结果
#main_process_id: 17808 <_MainProcess(MainProcess, started)>
#sing_process_parrnt_id: 18104
#sing...
#main_process_id: 17388 <Process(dance_process, started)>
#dance_process_parrnt_id: 17808
#dance...
#sing...
#dance...
#sing...
#dance...
三、多进程带参数
import multiprocessing
def show_info(name, age):
print(name, age)
if __name__ == '__main__':
#以元祖方式传参,元祖元素要和函数参数顺序保持一致
sub_process = multiprocessing.Process(target=show_info, args={'张三', 30})
sub_process.start()
#字典方式传参,字典的key要和函数里面的参数名保持一致,没有顺序要求
sub_process = multiprocessing.Process(target=show_info, kwargs={'age':20, 'name':'张三'})
sub_process.start()
四、进程注意点
1.进程之间不共享全局变量
2.主进程会等所有的子进程结束再结束
提示:对应linux和mac主进程执行的代码不会进程拷贝,window系统主进程执行的代码会进行拷贝,所以,对应window来说创建子进程的代码如果进程拷贝相当于无限制进行创建子进程,会报错
可以用if name == ‘main’:来判断是否是主模块来解决
import multiprocessing
import time
g_list = list()
def add_add_data():
for i in range(3):
g_list.append(i)
print('add', i )
time.sleep(0.3)
def read_data():
print('read', g_list)
if __name__ == '__main__':
add_process = multiprocessing.Process(target=add_add_data)
read_process = multiprocessing.Process(target=read_data)
add_process.start()
#当前进程(主进程)等待添加数据的进程执行完成以后代码再继续往下执行
add_process.join()
read_process.start()
#运行结果
#add 0
#add 1
#add 2
#read []
#结论:进程之间不共享全局变量
解决办法:
- 把子进程设置成为守护主进程,主进程退出,子进程直接销毁
# sub_process.daemon = True
- 退出主进程之前,先让子进程销毁
# sub_process.terminate()
import multiprocessing
import time
def task():
while True:
print('任务执行中')
time.sleep(0.2)
if __name__ == '__main__':
sub_process = multiprocessing.Process(target=task)
#把子进程设置成为守护主进程,主进程退出,子进程直接销毁
# sub_process.daemon = True
sub_process.start()
#主进程延时0.5s
time.sleep(0.5)
#退出主进程之前,先让子进程销毁
sub_process.terminate()
print('over')
#结论:主进程会等待子进程执行完成以后程序再推出