Python多进程编程-multiprocessing库
1.概述
进程(Process)是指计算机中已运行的程序,是系统进行资源分配和调度的基本单位,不同的进程之间互不干涉,每个进程都有自己的堆栈,它们之间的数据不共享。
在当代面向线程设计的计算机结构中,进程是线程的容器。进程是程序真正运行的实例,若干进程可能与同一个程序相关,且每个进程皆可以同步或异步的方式独立运行。
进程执行时的间断性,决定了进程可能具有多种状态。事实上,运行中的进程可能具有以下三种基本状态:
1)就绪状态(Ready):
进程已获得除处理器外的所需资源,等待分配处理器资源;只要分配了处理器进程就可执行。就绪进程可以按多个优先级来划分队列。例如,当一个进程由于时间片用完而进入就绪状态时,排入低优先级队列;当进程由I/O操作完成而进入就绪状态时,排入高优先级队列。
2)运行状态(Running):
进程占用处理器资源;处于此状态的进程的数目小于等于处理器的数目。在没有其他进程可以执行时(如所有进程都在阻塞状态),通常会自动执行系统的空闲进程。
3)阻塞状态(Blocked):
由于进程等待某种条件(如I/O操作或进程同步),在条件满足之前无法继续执行。该事件发生前即使把处理器资源分配给该进程,也无法运行。
与程序区别:
1.程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。而进程是程序在处理机上的一次执行过程,它是一个动态的概念。
2.程序可以作为一种软件资料长期存在,而进程是有一定生命期的。程序是永久的,进程是暂时的。 进程更能真实地描述并发,而程序不能;
3.进程是由进程控制块、程序段、数据段三部分组成; 进程具有创建其他进程的功能,而程序没有。
4.同一程序同时运行于若干个数据集合上,它将属于若干个不同的进程,也就是说同一程序可以对应多个进程。
5.在传统的操作系统中,程序并不能独立运行,作为资源分配和独立运行的基本单元都是进程。
2.多进程实战-文件的复制
# Authors:xaiobei
# ###文件的复制###
from multiprocessing import Process
import os,time
#copy函数
def copyFile(path,topath):
#以二进制形式读写,因为文件并非都是文本类型
with open(path,"rb") as fr:
data = fr.read()
with open(topath,"wb") as fw:
fw.write(data)
#os.getpid()返回进程号(PID),创建不同的子进程,PID不同
print("[子进程]: %s 启动"%os.getpid())
if __name__ == "__main__":
print("---主进程启动---")
start = time.time()
# 获取文件列表(这里是相对路径,可以改为绝对路径)
fileList = os.listdir("file")
#循环处理文件
for file in fileList:
#合成路径
path = os.path.join("file",file)
topath = os.path.join("tofile",file)
#循环创建子进程,分别处理不同的文件,与直接调用--copyFile(path,topath)---的区别是:
#1.直接调用时,一个文件复制完之后才能继续复制下一个
#2.创建子进程时可以不必等待上一个文件复制完成,把不同的任务分配给不同的子进程同时进行
#3.在处理大量文件时,多进程可以极大的提高效率,但由于创建进程比较耗时,在处理少量文件时效率甚至不如直接调用快
process = Process(target = copyFile,args=(path,topath)) #args参数是一个元组,当只传递一个参数时,表示为(x,)
# 开始子进程
process.start()
#子进程加入主进程,在所有子进程结束后,主进程才继续向下执行(主进程等待子进程执行完成)
process.join()
end = time.time()
time = end-start
print("---主进程结束---")
print("用时%.2f s"%time)
3.进程池
示意图:
# Authors:xaiobei
# ###文件的复制###
from multiprocessing import Pool
import os,time
def copyFile(path,topath):
with open(path,"rb") as fr:
data = fr.read()
with open(topath,"wb") as fw:
fw.write(data)
#os.getpid()返回进程号(PID),创建不同的子进程,PID不同 os.getppid()返回父进程(PID)
print("[子进程]: %s 启动"%os.getpid())
#在此停滞2s突出效果
time.sleep(2)
if __name__ == "__main__":
print("---主进程启动---")
start = time.time()
# 创建进程池,默认数CPU核心数,当参数大于默认值时,CPU的核心交替执行不同的进程
poo = Pool(2)
fileList = os.listdir("file")
for file in fileList:
path = os.path.join("file",file)
topath = os.path.join("tofile",file)
# 在进程池中加入进程,统一管理
poo.apply_async(copyFile,args=(path,topath))
# 当进程池close后,无法再向其中添加进程
poo.close()
# 进程池加入主进程,当进程池中所有子进程结束后,主进程才继续向下执行(主进程等待子进程执行完成)
poo.join()
end = time.time()
time = end-start
print("---主进程结束---")
print("用时%.2f s"%time)