进程池

主宰稳场 提交于 2020-03-25 08:34:44
#模块:Pool
#导入方法:from multiprocessing import Pool
#原理:
       进程池:一个池子,里边有固定数量的进程。这些进程一直处于待命状态,一旦有任务来,马上就有进程去处理。
       因为在实际业务中,任务量是有多有少的,如果任务量特别的多,不可能要开对应那么多的进程数
       开启那么多进程首先就需要消耗大量的时间让操作系统来为你管理它。其次还需要消耗大量时间让
       cpu帮你调度它。
       进程池还会帮程序员去管理池中的进程。
#模块方法:
       from multiprocessing import Pool
       p = Pool(os.cpu_count() + 1)        #规定进程池中的进程数量根据(CPU核数+1)
       
       三种方法:
         map(func,iterable)
         func:进程池中的进程执行的任务函数
         iterable: 可迭代对象,是把可迭代对象中的每个元素依次传给任务函数当参数

         apply(func,args=()): 同步的效率,也就是说池中的进程一个一个的去执行任务
         func:进程池中的进程执行的任务函数
         args: 可迭代对象型的参数,是传给任务函数的参数
         同步处理任务时,不需要close和join
         同步处理任务时,进程池中的所有进程是普通进程(主进程需要等待其执行结束)

         apply_async(func,args=(),callback=None): 异步的效率,也就是说池中的进程一次性都去执行任务
         func:进程池中的进程执行的任务函数
         args: 可迭代对象型的参数,是传给任务函数的参数
         callback: 回调函数,就是说每当进程池中有进程处理完任务了,返回的结果可以交给回调函数,由回调函数进行进一步的处理,回调函数只有异步才有,同步是没有的
         异步处理任务时,进程池中的所有进程是守护进程(主进程代码执行完毕守护进程就结束)
         异步处理任务时,必须要加上close和join

         回调函数的使用:
             进程的任务函数的返回值,被当成回调函数的形参接收到,以此进行进一步的处理操作
             回调函数是由主进程调用的,而不是子进程,子进程只负责把结果传递给回调函数

#使用方法:
#进程池中的同步处理的效率
from multiprocessing import Pool
import os
import time

#同步进程池
def func(num):
    num+=1
    return num

if __name__ == '__main__':
    #创建进程池对象
    p=Pool(os.cpu_count()+1) #进程池中进程的数量为CPU核数+1
    #计算代码执行到这一行的时间
    start = time.time()
    #创建10000个进程
    for i in range(10000):
        #进程池中同步进程的创建方式
        res=p.apply(func,args=(i,))# 同步处理这10000个任务,同步是指,哪怕我进程中有5个进程,也依旧是1个进程1个进程的去执行任务
        print(res)
    #计算同步进程消耗的时间
    end = time.time()
    print(end-start)
    
#############################
#进程池中异步处理的效率
#异步进程池
def func(num):
    num+=1
    return num

if __name__ == '__main__':
    #创建进程池对象
    p=Pool(os.cpu_count()+1) #进程池中进程的数量为CPU核数+1
    #计算代码执行到这一行的时间
    start = time.time()
    l = []
    #创建10000个进程
    for i in range(10000):
        #进程池中同步进程的创建方式
        res = p.apply_async(func,args=(i,))# 异步处理这100个任务,异步是指,进程中有5个进程,一下就处理5个任务,接下来哪个进程处理完任务了,就马上去接收下一个任务
        l.append(res)
    #必须先关闭进程池
    p.close()
    #再让主进程等待子进程的执行完毕,否则主进程执行完子进程可能还没执行完就随着主进程的结束而结束了(守护进程)
    p.join()
    #计算异步进程消耗的时间
    end = time.time()
    [print(i.get()) for i in l]
    print(end-start)
#############
##小结:异步进程的效率在一定的相同情况下优于同步进程





################################
##异步进程中的回调函数的应用
from multiprocessing import Pool
import requests
import time,os

def func(url):
    res = requests.get(url)
    print('子进程的pid:%s,父进程的pid:%s'%(os.getpid(),os.getppid()))
    # print(res.text)
    if res.status_code == 200:
        return url,res.text

def cal_back(sta):
    url,text = sta
    print('回调函数的pid', os.getpid())
    with open('a.txt','a',encoding='utf-8') as f:
        f.write(url + text)
    # print('回调函数中!',url)

if __name__ == '__main__':
    p = Pool(5)
    l = ['https://www.baidu.com',
         'http://www.jd.com',
         'http://www.taobao.com',
         'http://www.mi.com',
         'http://www.cnblogs.com',
         'https://www.bilibili.com',
         ]
    print('主进程的pid',os.getpid())
    for i in l:
        p.apply_async(func, args=(i,),callback=cal_back)#
        # 异步执行任务func,每有一个进程执行完任务后,在func中return一个结果,结果会自动的被callback指定的函数,当成形式参数来接收到
    p.close()
    p.join()

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!