zoukankan      html  css  js  c++  java
  • python多进程实例详解

    写在前面:python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程。Python提供了非常好用的多进程包multiprocessing,只需要定义一个函数,Python会完成其他所有事情。借助这个包,可以轻松完成从单进程到并发执行的转换。

    1.multiprocessing模块提供了一个Process类来代表一个进程对象

    import os
    import time
    import multiprocessing
    def run_proc(name): # 子进程要执行的代码
        print '运行子进程 %s ,子进程号为(%s)...' % (name, os.getpid())
        print "我的处理内容是:%s+%s=?" % (name,name)
        return name
    
    if __name__=='__main__':
        start = time.time()
        print '父进程号为 %s.' % os.getpid()
        print('----------------------------------------')
        job = []
        for i in range(3):
            p = multiprocessing.Process(target=run_proc, args=(i,))#多进程
            job.append(p)
            print '子进程%d开启...'%i
            p.start() #
            print '子进程%d结束...'    %i
            print
    #加join()可以让主线程一直等待全部的子线程结束之后,主线程自身才结束,程序退出
    for t in job: t.join()#join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步 end = time.time() print end-start

    运行结果如下:

    父进程号为 4924.
    ----------------------------------------
    子进程0开启...
    子进程0结束...
    
    子进程1开启...
    子进程1结束...
    
    子进程2开启...
    运行子进程 0 ,子进程号为(5516)...
    我的处理内容是:0+0=?
    运行子进程 1 ,子进程号为(5517)...
    我的处理内容是:1+1=?
    运行子进程 2 ,子进程号为(5523)...
    我的处理内容是:2+2=?
    子进程2结束...
    
    0.0220789909363

    如果想要返回多进程process处理得到的结果,只需要利用multiprocessing 中的Manager类即可,稍改代码:

    import os
    import time
    from multiprocessing import Manager
    def run_proc(name,return_list): # 子进程要执行的代码
        print '运行子进程 %s ,子进程号为(%s)...' % (name, os.getpid())
        print "我的处理内容是:%s+%s=?" % (name,name)
        return_list.append(name)
    
    if __name__=='__main__':
        print '父进程号为 %s.' % os.getpid()
        print('----------------------------------------')
        
        manager = Manager()
        return_list = manager.list() 
        #return_dict = manager.dict() 也可以使用字典dict
        job = []
        for i in range(3):
            p = multiprocessing.Process(target=run_proc, args=(i,return_list))#多进程
            job.append(p)
            print '子进程%d开启...'%i
            p.start()
            print '子进程%d结束...'    %i
            print
        for t in job:
            t.join()
        print "所有子进程处理得到的结果都在return_list中,值为:",return_list

    运行结果如下:

    父进程号为 4924.
    ----------------------------------------
    子进程0开启...
    子进程0结束...
    
    子进程1开启...
    子进程1结束...
    
    子进程2开启...
    运行子进程 0 ,子进程号为(5614)...
    我的处理内容是:0+0=?
    运行子进程 1 ,子进程号为(5616)...
    我的处理内容是:1+1=?
    运行子进程 2 ,子进程号为(5623)...
    我的处理内容是:2+2=?
    子进程2结束...
    
    所有子进程处理得到的结果都在return_list中,值为: [0, 1, 2]

    2.Pool:如果要启动大量的子进程,可以用进程池的方式批量创建子进程:

    from multiprocessing import Pool
    import os, time, random
    
    def long_time_task(name):
        print '运行任务 %s ,子进程号为(%s)...' % (name, os.getpid())
        
        print "我就是子进程号为(%s)处理的内容" % (os.getpid())
        start = time.time()
        time.sleep(random.random() * 3)
        end = time.time()
        print '任务 %s 运行了 %0.2f 秒.' % (name, (end - start))
        return name
    
    if __name__=='__main__':
        print '父进程号为 %s.' % os.getpid()
        rst = []
        p = Pool(4)  #进程池中含有4个子进程
        for i in range(5): #4个子进程完成5个任务,所以有一个任务是需要等某个进程空闲再处理
            a = p.apply_async(long_time_task, args=(i,)) #a是进程处理函数long_time_task的返回结果
            rst.append(a)  #将次得到的结果添加到数组rst中去
        print '等待所有子进程结束...'
        p.close()
        p.join()#等待所有子进程执行完毕。调用join()之前必须先调用close(),调用close()之后就不能继续添加新的Process了。
        print '所有子进程结束...'

    运行结果如下:

    父进程号为 3378.
    运行任务 0 ,子进程号为(4621)...
    运行任务 2 ,子进程号为(4624)...
    运行任务 1 ,子进程号为(4622)...
    我就是子进程号为(4621)处理的内容
    我就是子进程号为(4622)处理的内容
    运行任务 3 ,子进程号为(4627)...
    我就是子进程号为(4624)处理的内容
    我就是子进程号为(4627)处理的内容
    任务 1 运行了 0.16 秒.
    运行任务 4 ,子进程号为(4622)...
    我就是子进程号为(4622)处理的内容
    等待所有子进程结束...
    任务 2 运行了 0.98 秒.
    任务 4 运行了 0.89 秒.
    任务 3 运行了 2.25 秒.
    任务 0 运行了 2.89 秒.
    所有子进程结束...

    直接输出rst不会得到想要的结果:

    rst
    运行结果:
    [<multiprocessing.pool.ApplyResult at 0x7ffa6c682c90>,
     <multiprocessing.pool.ApplyResult at 0x7ffa6c587590>,
     <multiprocessing.pool.ApplyResult at 0x7ffa6c587610>,
     <multiprocessing.pool.ApplyResult at 0x7ffa6c5876d0>,
     <multiprocessing.pool.ApplyResult at 0x7ffa6c587790>]

    这是需要用到.get()方法:

    rst = [i.get() for i in rst]
    rst
    运行结果:
    [0, 1, 2, 3, 4]
  • 相关阅读:
    Atitit  atiMail atiDns新特性 v2  q39
    Atitit  atiMail atiDns新特性 v2  q39
    Atitit.aticmd v4  新特性q39 添加定时器释放功能
    Atitit.aticmd v4  新特性q39 添加定时器释放功能
    Atitit. Atiposter 发帖机 新特性 poster new feature   v7 q39
    Atitit. Atiposter 发帖机 新特性 poster new feature   v7 q39
    Atitit.编程语言and 自然语言的比较and 编程语言未来的发展
    Atitit.编程语言and 自然语言的比较and 编程语言未来的发展
    atitit.解决struts2 SpringObjectFactory.getClassInstance NullPointerException  v2 q31
    知也atitit.解决struts2 SpringObjectFactory.getClassInstance NullPointerException  v2 q31无涯 - I
  • 原文地址:https://www.cnblogs.com/USTC-ZCC/p/11230827.html
Copyright © 2011-2022 走看看