Python多进程编程:multiprocessing模块详解

这里写目录标题

  • 一、进程概念
  • 二、python多进程
  • 获取进程信息
  • current_process()
  • OS 模块
  • 三、进程特点
  • 一、进程概念

    进程(Process)是资源分配的最小单位,它是操作系统进行资源分配和调度运行的基本单位,通俗理解:一个正在运行的程序就是一个进程。

    注: 一个程序运行后至少有一个进程

    二、python多进程

    在python中使用多进程我们需要导入 multiprocessing 模块

    import multiprocessing
    

    实例演示:

    1. 我们先定义两个函数,然后创建子进程去调用它们
    import time
    
    def mission1(n):
        for i in range(1, n + 1):
            print(f'第{i}次执行任务一。')
            time.sleep(0.2)
    
    
    def mission2(n):
        for i in range(1, n + 1):
            print(f"第{i}次执行任务二。")
            time.sleep(0.2)
    

    每个函数每次循环都sleep 0.2秒目的是为了之后演示进程之间是同步执行的情况,否则程序运行太快没办法体现。

    我们先试着直接调用它们:

    mission1(5)
    mission2(5)
    """
    结果:
    第1次执行任务一。
    第2次执行任务一。
    第3次执行任务一。
    第4次执行任务一。
    第5次执行任务一。
    第1次执行任务二。
    第2次执行任务二。
    第3次执行任务二。
    第4次执行任务二。
    第5次执行任务二。
    """
    

    结果:先执行了mission1 再执行了mission2

    1. 子进程依赖于父进程创建,因而我们要创建两个子进程,那么必须在父进程里面去创建。
      python运行文件的时候会创建一个主进程也就是 MainProcess,因而我们必须在main里面去操作子进程:
    if __name__ == '__main__':
    		pass
    
    1. 接着我们创建子进程对象:
    if __name__ == '__main__':
        p1 = multiprocessing.Process(target=mission1,  args=(5,))
        p2 = multiprocessing.Process(target=mission2,  kwargs={'n': 5})
    

    multiprocessing.Process(group=None, target=None, name=None, args=(), kwargs={}) :
    target—表示调用对象,即子进程要执行的任务(回调函数入口地址)
    args—表示以元组的形式向子任务函数传参,元组方式传参一定要和参数的顺序保持一致
    kwargs—表示以字典的方式给子任务函数传参,字典方式传参字典中的key要和参数名保持一致
    name—为子进程的名称

    进程运行:

        p1.start()
        p2.start()
    
    1. 完整代码:
    import multiprocessing
    
    import time
    
    def mission1(n):
        for i in range(1, n + 1):
            print(f'第{i}次执行任务一。')
            time.sleep(0.2)
    
    
    def mission2(n):
        for i in range(1, n + 1):
            print(f"第{i}次执行任务二。")
            time.sleep(0.2)
    
    
    if __name__ == '__main__':
        p1 = multiprocessing.Process(target=mission1,  args=(5,)) # 注意单元素的元组格式
        p2 = multiprocessing.Process(target=mission2,  kwargs={'n': 5})
    
        p1.start()
        p2.start()
     
    """
    结果:
    第1次执行任务一。
    第1次执行任务二。
    第2次执行任务一。
    第2次执行任务二。
    第3次执行任务一。
    第3次执行任务二。
    第4次执行任务一。
    第4次执行任务二。
    第5次执行任务一。
    第5次执行任务二。
    """
    

    结果显示:两个函数在两个子进程中同时执行。(每次执行顺序可能有略微差别)

    获取进程信息

    current_process()

    获取当前进程的信息:name(进程名称) 和 pid (进程ID)

    def mission1(user, n):
        print(f"mission-1子进程:{multiprocessing.current_process().name}")
        print(f"mission-1子进程ID:{multiprocessing.current_process().pid}")
        for i in range(1, n + 1):
            print(f"用户{user}正在第{i}次执行任务一。")
            time.sleep(0.2)
    

    OS 模块

    可以使用os模块中的getpid()获取当前进程的ID 以及 getppid()获取当前进程的父进程ID。

    import os
    def mission2(user, n):
        print(f"mission-2子进程:{multiprocessing.current_process().name}")
        print(f"mission-2子进程ID:{os.getpid()}")
        print(f"mission-2子进程的父进程为:{os.getppid()}")
        for i in range(1, n + 1):
            print(f"用户{user}正在第{i}次执行任务二。")
            time.sleep(0.2)
    

    完整代码:

    import multiprocessing
    import time
    import os
    
    
    def mission1(user, n):
        print(f"mission-1子进程:{multiprocessing.current_process().name}")
        print(f"mission-1子进程ID:{multiprocessing.current_process().pid}")
        print(f"mission-1子进程的父进程为:{os.getppid()}")
        for i in range(1, n + 1):
            print(f"用户{user}正在第{i}次执行任务一。")
            time.sleep(0.2)
    
    
    def mission2(user, n):
        print(f"mission-2子进程:{multiprocessing.current_process().name}")
        print(f"mission-2子进程ID:{os.getpid()}")
        print(f"mission-2子进程的父进程为:{os.getppid()}")
        for i in range(1, n + 1):
            print(f"用户{user}正在第{i}次执行任务二。")
            time.sleep(0.2)
    
    if __name__ == '__main__':
        print(f"主进程的ID为:{multiprocessing.current_process().pid}")
        print(f"主进程的父进程ID为:{os.getppid()}")
        print(f'--------主进程{multiprocessing.current_process().name}开始执行--------')
    
        p1=multiprocessing.Process(target=mission1,name='mission-1',args=('张三',5))
        p2=multiprocessing.Process(target=mission2,name='mission-2',args=('李四',5))
    
        p1.start()
        p2.start()
    """
    主进程的ID为:7500
    主进程的父进程ID为:39284
    --------主进程MainProcess开始执行--------
    mission-2子进程:mission-2
    mission-2子进程ID:40552
    mission-2子进程的父进程为:7500
    用户李四正在第1次执行任务二。
    mission-1子进程:mission-1
    mission-1子进程ID:46296
    mission-1子进程的父进程为:7500
    用户张三正在第1次执行任务一。
    用户李四正在第2次执行任务二。
    用户张三正在第2次执行任务一。
    用户李四正在第3次执行任务二。
    用户张三正在第3次执行任务一。
    用户李四正在第4次执行任务二。
    用户张三正在第4次执行任务一。
    用户李四正在第5次执行任务二。
    用户张三正在第5次执行任务一。
    
    """
    

    两个子进程的父ID是相同的就是MainProcess这个主进程的ID

    三、进程特点

    1. 多进程之间不会共享全局变量

    2. 主进程会默认等待子进程结束而结束 但可以通过设置来让子进程跟着主进程结束而结束

    正常情况:

    import multiprocessing
    import time
    
    def mission1(user, n):
        for i in range(1, n + 1):
            print(f"用户{user}正在第{i}次执行任务一。")
            time.sleep(0.1)
    
    if __name__ == '__main__':
        print(f'--------主进程{multiprocessing.current_process().name}开始执行--------')
        p1 = multiprocessing.Process(target=mission1, name='mission-1', args=('张三', 5))
        p1.start()
        time.sleep(0.4) # 让主进程多执行一会儿
        print(f'----------主进程:{multiprocessing.current_process().name}最后一行代码执行完毕---------')
    
    """
    --------主进程MainProcess开始执行--------
    用户张三正在第1次执行任务一。
    用户张三正在第2次执行任务一。
    ----------主进程:MainProcess最后一行代码执行完毕---------
    用户张三正在第3次执行任务一。
    用户张三正在第4次执行任务一。
    用户张三正在第5次执行任务一。
    """
    

    正常情况下,主进程(最后一行代码执行完了)仍然会等待子进程(p1 mission-1)执行完毕.

    使用守护进程或者终止进程

    import multiprocessing
    import time
    
    
    def mission1(user, n):
        for i in range(1, n + 1):
            print(f"用户{user}正在第{i}次执行任务一。")
            time.sleep(0.1)
    
    
    if __name__ == '__main__':
        print(f'--------主进程{multiprocessing.current_process().name}开始执行--------')
    
        p1 = multiprocessing.Process(target=mission1, name='mission-1', args=('张三', 5))
        # 方式1: 开启子进程前提前设置守护主进程
        p1.daemon = True
        p1.start()
        time.sleep(0.4)  # 让主进程多执行一会儿
        # p1.terminate()
        print(f'----------主进程:{multiprocessing.current_process().name}最后一行代码执行完毕---------')
    
    """
    --------主进程MainProcess开始执行--------
    用户张三正在第1次执行任务一。
    用户张三正在第2次执行任务一。
    ----------主进程:MainProcess最后一行代码执行完毕---------
    """
    

    我们发现子进程还没执行结束就被终止了。

    1. 多进程之间是无序的

    作者:黑鹿022

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python多进程编程:multiprocessing模块详解

    发表回复