进程池
当需要创建的子进程数量不多时,可以直接利用multiprocessing中的Process动态成生多个进程,但如果是上百甚至上千个目标,手动的去创建进程的工作量巨大,此时就可以用到multiprocessing模块提供的Pool方法。
初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会用之前的进程来执行新的任务
用进程池来实现一个文件拷贝的案例:
import multiprocessing
import time
import os
# 读写文件
def copy_file(temp_file_dir_path, new_dir_path, file_name):
data = None
# 读取文件
with open(temp_file_dir_path, "rb") as f_read:
data = f_read.read()
if data:
# 写入文件
new_dir_path += "\\" + file_name
f_write = open(new_dir_path, "wb")
f_write.write(data)
f_write.close()
time.sleep(1)
# 递归获取文件
def get_copy_file(dict1, dir_path, po, new_dir_path):
"""
:param dir_path:原始文件夹路径
:param po:进程池
:param new_dir_path:新文件夹路径
:return:
"""
# 获取文件夹中的所有文件
file_names = os.listdir(dir_path)
for file_name in file_names:
# 文件或者文件夹目录
temp_file_dir_path = dir_path + "\\" + file_name
# 判断是否是文件夹,如果是就递归
if os.path.isdir(temp_file_dir_path):
# 如果是文件夹直接递归在次扫描文件,并且将新地址重新整合,以及创建新文件夹
# 这里不能使用加等于,因为有多个文件夹的话将会出现不停的叠加字符串导致路径不对
new_dest_dir_path = new_dir_path + "\\" + file_name
# print(new_dest_dir_path)
# 创建新文件夹
os.mkdir(new_dest_dir_path)
# 然后开始递归
get_copy_file(dict1, temp_file_dir_path, po, new_dest_dir_path)
# 判断是否是文件,是文件就执行copy功能
elif os.path.isfile(temp_file_dir_path):
# 储存文件名
dict1["queue"].put(file_name)
dict1["len"] += 1
# 使用进程池来copy文件
po.apply_async(copy_file, args=(temp_file_dir_path, new_dir_path, file_name))
# 进程池copy
def main():
dir_path = "D:\视频\Python\python笔记"
new_dir_path = dir_path + "【new】"
try:
# 创建新文件夹
os.mkdir(new_dir_path)
except:
pass
# 创建进程池
po = multiprocessing.Pool(5)
# 使用queue来实现进度条
dict1 = multiprocessing.Manager().dict()
q = multiprocessing.Manager().Queue()
# 来储存文件名和文件数量
dict1["queue"] = q
dict1["len"] = 0
print(dict1)
# 获取要复制的文件并且复制
get_copy_file(dict1, dir_path, po, new_dir_path)
# 关闭子进程
po.close()
# 等待子进程完结后在结束主进程
# po.join()
break_count = 0
while True:
break_count += 1
file_name = dict1["queue"].get()
# 如果复制的数据数量与总数一致则表示已经复制完成,可以跳出循环
num = break_count / dict1["len"]
print(f"拷贝进度为:%% %.2f 文件名为:{file_name}" % (num * 100))
if dict1["len"] <= break_count:
break
print(dict1["len"])
if __name__ == "__main__":
main()
作者:阿超