进程池

当需要创建的子进程数量不多时,可以直接利用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()

作者:阿超