zoukankan      html  css  js  c++  java
  • Python多进程

    参考:https://www.liaoxuefeng.com/wiki/1016959663602400/1017627212385376

    进程

    在操作系统中一个任务对应一个进程,如打开了word就启动了一个word进程

    线程

    一个进程下可以有多个线程至少一个线程

    Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)。

    同时执行多个任务

    • 多进程模式:启动多个进程,每个进程虽然只有一个线程,但多个进程可以一块执行多个任务。
    • 多线程模式:启动一个进程,在一个进程内启动多个线程,这样,多个线程也可以一块执行多个任务。
    • 多进程 + 多线程模式 :启动多个进程,每个进程再启动多个线程,这样同时执行的任务就更多了,当然这种模型更复杂,实际很少采用。

    multiprocessing 跨平台的多进程模块

    # multiprocessing 中 使用 Process 代表一个进程对象
    
    from multiprocessing import Process
    import os
    
    
    # 子进程运行的代码;
    # proc_name: str ,表示 形参proc_name 需要是str类型 :
    # https://docs.python.org/zh-cn/3.7/library/typing.html?highlight=typing#module-typing
    def run_proc(proc_name: str):
        print(f'子进程运行,进程名称 { proc_name },其进程ID为:{ os.getpid() }')
    
    
    def run_proc1():
        print(f'子进程运行,其进程ID为:{ os.getpid() }')
    
    
    def run_proc2(name: str, now: str):
        print(f'子进程运行,进程名称 { name },其进程ID为:{ os.getpid() }, 当前时间 { now }')
    
    
    if __name__ == '__main__':
        print(F"主进程ID:{ os.getpid() }")
        # 创建一个进程, target=需执行的函数, args=(需执行的函数参数, ), 可以是多个,1个也需要元组形式传递参数
        p = Process(target=run_proc, args=('测试进程', ))
        # 需执行函数无参数时,创建进程
        p1 = Process(target=run_proc1)
        p2 = Process(target=run_proc2, args=('name', 'fff', ))
        print("子进程将启动!")
        # start 方法启动进程
        p.start()
        p1.start()
        p2.start()
        # join 方法等待子进程结束后继续往下运行
        p.join()
        p1.join()
        p2.join()
        print('子进程结束')
    

    Pool:进程池,批量创建进程

    from multiprocessing import Pool
    
    import os, time, random
    
    
    def long_time_task(name):
        print(f'任务:{ name }({ os.getpid()})运行')
        start = time.time()
        time.sleep(random.random() * 3)
        end = time.time()
        print(f'任务 { name } 运行耗时 { end-start: .2f} 秒')
    
    
    if __name__ == '__main__':
        print(f'主进程{ os.getpid() }')
        # 创建4个进程: Pool的默认大小是CPU的核心数,如果是8核cpu,你要提交至少9个线程才能看到效果
        p = Pool(4)
        for i in range(5):
            p.apply_async(long_time_task, args=(i,))
        print('等待所有子进程运行完成')
        # 执行该方法后不能继续添加新的Process
        p.close()
        # 等待所有子进程执行完毕
        p.join()
        print('所有进程运行完毕!')
    

    运行结果:

    /Users/zy7y/PycharmProjects/demo/venv/bin/python /Users/zy7y/PycharmProjects/demo/pool_demo.py
    主进程1893
    等待所有子进程运行完成
    任务:0(1894)运行
    任务:1(1895)运行
    任务:2(1896)运行
    任务:3(1897)运行
    任务 1 运行耗时  0.36 秒
    任务:4(1895)运行
    任务 2 运行耗时  1.08 秒
    任务 0 运行耗时  2.77 秒
    任务 3 运行耗时  2.81 秒
    任务 4 运行耗时  2.45 秒
    所有进程运行完毕!
    

    结果解读:

    任务0,1,2,3是立刻执行的,任务4是等前面某个任务完成后才执行,这是因为Pool的默认大小在本机是4,因此最多同时拥有4个进程

    子进程(暂未理解)

    subprocess实现方便启动一个子进程,控制其输入和输出

    https://www.liaoxuefeng.com/wiki/1016959663602400/1017628290184064

    进程间通信

    Python的multiprocessing模块包装了底层的机制,提供了QueuePipes等多种方式来交换数据。

    import os
    import random
    import time
    from multiprocessing import Process, Queue
    
    
    # 写数据进程执行的代码
    def write(q):
        print(f"用来写入的进程{os.getpid()}")
        for value in ['A', 'B', 'C']:
            print(f'把{ value }放入Queue(队列)中')
            q.put(value)
            time.sleep(random.random())
    
    
    # 读数据进程执行的代码
    def read(q):
        print(f'用来读取的进程{os.getpid()}')
        while True:
            value = q.get(True)
            print(f'从队列中获取 {value}')
    
    
    if __name__ == '__main__':
        # 主进程创建Queue,并传递给各个子进程
        q = Queue()
        pw = Process(target=write, args=(q,))
        pr = Process(target=read, args=(q,))
    
        # 启动子进程pw, 写入:
        pw.start()
        # 启动子进程pr, 读取:
        pr.start()
    
        # 等待pw结束
        pw.join()
    
        # pr进程是个死循环,无法自己结束,只能强行终止:
        pr.terminate()
    
    

    运行结果:

    /Users/zy7y/PycharmProjects/demo/venv/bin/python /Users/zy7y/PycharmProjects/demo/queue_demo.py
    用来写入的进程2226
    把A放入Queue(队列)中
    用来读取的进程2227
    从队列中获取 A
    把B放入Queue(队列)中
    从队列中获取 B
    把C放入Queue(队列)中
    从队列中获取 C
    
    Process finished with exit code 0
    
    作者:zy7y
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文链接,否则保留追究法律责任的权利。
  • 相关阅读:
    Xenu Link Sleuth简单使用
    C#简单游戏外挂制作(以Warcraft Ⅲ为例)
    Silverlight InkPresenter 实现路径回放的探索
    Microsoft Virtual Earth Silverlight Map Control (CTP)快速上手
    【Azure实例】有趣的Silverlight应用:录播简笔画
    Azure Services Platform 入门系列文章索引页
    javascript原型的类继承
    javascript给类添加的方法
    checkbox 全选
    【nodejs】 在 Ubuntu 12.04 安裝 Node.js【转】
  • 原文地址:https://www.cnblogs.com/zy7y/p/13339910.html
Copyright © 2011-2022 走看看