python 进程实现多任务

1.导入进程模块 import multiprocessing1.2 Process进程类的语法结构如下:Process([group [, target [, name [, args [, kwargs]]]]])group:指定进程组,目前只能使用Nonetarget:执行的目标任务名name:...

1.导入进程模块

    import multiprocessing

1.2 Process进程类的语法结构如下:

Process([group [, target [, name [, args [, kwargs]]]]])

  • group:指定进程组,目前只能使用None
  • target:执行的目标任务名
  • name:进程名字
  • args:以元组方式给执行任务传参
  • kwargs:以字典方式给执行任务传参

Process创建的实例对象的常用方法:

  • start():启动子进程实例(创建子进程)
  • join([timeout]):是否等待子进程执行结束,或等待多少秒
  • terminate():不管任务是否完成,立即终止子进程

Process创建的实例对象的常用属性:

  • name:当前进程的别名,默认为Process-N,N为从1开始递增的整数
  • pid:当前进程的pid(进程号)multiprocessing.current_process().pid    或os.getpid()
  • 获取父进程编号:os.getppid()

2.进程注意点

  • 进程之间不共享全局变量(创建子进程其实是对主进程进行拷贝,进程进程之间相互独立,访问的全局变量不是同一个)需要使用Queue
  • 主进程默认会等待所有的子进程执行完成后程序才会退出
  • 可以为设置守护主进程 ,但是只能通过sub_process.daemon = True
  • 可以直接销毁子进程,主进程退出之前把子进程销毁,sub_process.terminate()

3.进程间通信

    queue添加数据:

    queue =  multiprocessing.Queue(maxsize=-1)  # -1表示添加任意多个数据

    queue.put(数据)  # queue可以放入任何类型的数据 ,如果队列满了,数据会进行等待,直到消息队列有空闲位置才放入数据

    queue.put_nowait(数据)#  队列如果满了,此方法会报错

    queue判断队列是否满了

    result = queue.full()  # 若满了返回True

    result = queue.empty() # 坑点,此方法判断消息队列不靠谱 ,不推荐使用

    queue.qusize()  # 查看当前队列里消息的个数

    queue获取数据

    value = queue.get()  # 队列中的元素是FIFO(先进先出)

    value = queue.get_nowait()  # 若队列为空立即报错,不推荐使用

利用消息队列完成进程通信

import multiprocessing
import time


# 添加数据到指定队列
def add_data(current_queue):
    # 循环往指定队列里面添加数据
    for value in ["苹果", "香蕉", "西瓜", "榴莲", "山竹"]:
        # 判断队列是否满了
        if current_queue.full():
            print("队列满了")
            break

        current_queue.put(value)
        print("add_data:", value)
        time.sleep(0.2)


# 读取数据从指定队列
def read_data(current_queue):
    while True:
        #if current_queue.empty():
        if current_queue.qsize() == 0:
            print("队列空了")
            break

        value = current_queue.get()
        print("read_data:", value)


if __name__ == '__main__':

    # 创建消息队列
    queue = multiprocessing.Queue(3)

    # 添加数据的进程
    add_data_process = multiprocessing.Process(target=add_data, args=(queue,))
    read_data_process = multiprocessing.Process(target=read_data, args=(queue,))

    # 启动进程执行对应的程序
    add_data_process.start()
    # 主进程等待添加数据的子进程执行完成以后再启动读取数据的进程
    add_data_process.join()
    read_data_process.start()

进程池

用来自动创建大量线程,process_pool = multiprocessing.Pool(max_size)

 初始化进程池时,可以指定一个最大进程数,当有新的请求提交到Pool时,如果池内有空闲进程则使用该进程,若无空闲进程,且进程池还未达到最大值,那么久会创建一个新的进程来执行该请求,若达到最大值,那么该进程就会等待,直到池中有进程结束,才会使用之前的进程来执行新的任务。

进程池分为同步执行任务和异步执行任务。

同步执行任务:process_pool.apply(work),默认创建的子进程为守护主进程的,但主进程会被阻塞到子进程执行结束

异步执行任务:process_pool.apply_async(work),创建的子进程是守护主进程的,但它是非阻塞的。

主进程需要等待进程池把所有任务完成才能退出

pool.close()  # 关闭进程池,明确告诉主进程不再接受其它任务

pool.join()  # 等待进程池完成所有任务

demo 进程池完成多任务版文件夹拷贝

import os
import shutil  # 文件操作的高级模块
import multiprocessing
import time


# 拷贝文件的操作
def copy_work(src_dir_path, dst_dir_path, file_name):
    src_file_path = src_dir_path + "/" + file_name  # test/1.txt
    dst_file_path = dst_dir_path + "/" + file_name
    print(multiprocessing.current_process().pid)
    # 打开目标文件
    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_path = "test"
    # 目标目录的路径
    dst_dir_path = "/home/python/Desktop/test"
    # 判断目标目录是否在桌面存在
    if os.path.exists(dst_dir_path):
        # 代码执行到此,说明桌面上有指定的目标目录,递归删除非空目录
        shutil.rmtree(dst_dir_path)  
    os.mkdir(dst_dir_path)
    file_name_list = os.listdir(src_dir_path)
    # 创建进程池
    pool = multiprocessing.Pool(3)
    for file_name in file_name_list:
        # print(file_name)
        # 使用进程池以异步的方式完成多任务文件的拷贝
        pool.apply_async(copy_work, args=(src_dir_path, dst_dir_path, file_name))

    # 关闭进程池
    pool.close()
    pool.join()

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

本文标题为:python 进程实现多任务