进程池Pool

  • 1. 进程池的概念
  • 2. 进程池同步执行任务
  • 3. 进程池异步执行任务
  • 4. 文件夹拷贝器-多任务



1. 进程池的概念

池子里面放的是进程,进程池会根据任务执行情况自动创建进程,而且尽量少创建进程,合理利用进程池中的进程完成多任务

当需要创建的子进程数量不多时,可以直接利用multiprocessing中的Process动态成生多个进程,但如果是上百甚至上千个目标,手动的去创建进程的工作量巨大,此时就可以用到multiprocessing模块提供的Pool方法。

初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会用之前的进程来执行新的任务.

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)

运行结果:

复制中... 100512
复制中... 68128
复制中... 98924
复制中... 100512
复制中... 68128

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()

执行结果:

复制中... 122872
复制中... 61772
复制中... 114636
复制中... 122872
复制中... 114636

multiprocessing.Pool常用函数解析:

  • apply(func[, args[, kwds]]): 阻塞方式调用函数,args表示以元组方式给函数传参,kwds表示以字典方式给函数传参
  • apply_async(func[, args[, kwds]]) :使用非阻塞方式调用函数,args表示以元组方式给函数传参,kwds表示以字典方式给函数传参
  • close():关闭Pool,使其不再接受新的任务;
  • terminate():不管任务是否完成,立即终止;
  • join():主进程阻塞,等待子进程的退出, 必须在close或terminate之后使用;

4. 文件夹拷贝器-多任务

import os
import shutil
import multiprocessing
# import time


# 文件拷贝任务
def copy_work(src_dir, dst_dir, file_name):
    # 查看进程对象
    pid = multiprocessing.current_process().pid
    print(pid)
    # 拼接源文件的路径
    src_file_path = src_dir + "/" + file_name
    # 拼接目标文件的路径
    dst_file_path = dst_dir + "/" + file_name
    with open(dst_file_path, "wb") as dst_file:
        # 打源文件读取文件中的数据
        with open(src_file_path, "rb") as src_file:
            while True:
                # 读取数据
                src_file_data = src_file.read(1024)
                if src_file_data:
                    # 写入到目标文件里面
                    dst_file.write(src_file_data)
                else:
                    break
    # time.sleep(0.5)

if __name__ == '__main__':
    # 源目录
    src_dir = "test"
    # 目标目录
    dst_dir = "/home/python/Desktop/test"

    # 判断文件夹是否存在
    if os.path.exists(dst_dir):
        # 存在则删除文件夹及文件夹里面的所有文件
        shutil.rmtree(dst_dir)

    # 创建目标文件夹
    os.mkdir(dst_dir)
    # 获取源目录里面文件的列表
    file_name_list = os.listdir(src_dir)
    # 创建进程池
    pool = multiprocessing.Pool(3)
    # 遍历文件里面获取文件名
    for file_name in file_name_list:
        # 使用进程池执行拷贝任务
        pool.apply_async(copy_work, (src_dir, dst_dir, file_name))

    # 关闭进程池
    pool.close()
    # 主进程等待进程池执行完成以后程序再退出
    pool.join()

进程池在执行任务的时候会尽量少创建进程,合理利用现有进程完成多任务,这样可以减少资源开销