• 回调函数


    需要回调函数的场景:进程池中任何一个任务一旦处理完了,就立即告知主进程:我好了额,你可以处理我的结果了。主进程则调用一个函数去处理该结果,该函数即回调函数

    我们可以把耗时间(阻塞)的任务放到进程池中,然后指定回调函数(主进程负责执行),这样主进程在执行回调函数时就省去了I/O的过程,直接拿到的是任务的结果。

    from multiprocessing import Pool
    import requests
    import json
    import os
    
    def get_page(url):
        print('<进程%s> get %s' %(os.getpid(),url))
        respone=requests.get(url)
        if respone.status_code == 200:
            return {'url':url,'text':respone.text}
    
    def pasrse_page(res):
        print('<进程%s> parse %s' %(os.getpid(),res['url']))
        parse_res='url:<%s> size:[%s]
    ' %(res['url'],len(res['text']))
        with open('db.txt','a') as f:
            f.write(parse_res)
    
    
    if __name__ == '__main__':
        urls=[
            'https://www.baidu.com',
            'https://www.python.org',
            'https://www.openstack.org',
            'https://help.github.com/',
            'http://www.sina.com.cn/'
        ]
    
        p=Pool(3)
        res_l=[]
        for url in urls:
            res=p.apply_async(get_page,args=(url,),callback=pasrse_page)
            res_l.append(res)
    
        p.close()
        p.join()
        print([res.get() for res in res_l]) #拿到的是get_page的结果,其实完全没必要拿该结果,该结果已经传给回调函数处理了
    
    '''
    打印结果:
    <进程3388> get https://www.baidu.com
    <进程3389> get https://www.python.org
    <进程3390> get https://www.openstack.org
    <进程3388> get https://help.github.com/
    <进程3387> parse https://www.baidu.com
    <进程3389> get http://www.sina.com.cn/
    <进程3387> parse https://www.python.org
    <进程3387> parse https://help.github.com/
    <进程3387> parse http://www.sina.com.cn/
    <进程3387> parse https://www.openstack.org
    [{'url': 'https://www.baidu.com', 'text': '<!DOCTYPE html>
    ...',...}]
    '''
    爬虫案例
    from multiprocessing import Pool
    import time,random
    import requests
    import re
    
    def get_page(url,pattern):
        response=requests.get(url)
        if response.status_code == 200:
            return (response.text,pattern)
    
    def parse_page(info):
        page_content,pattern=info
        res=re.findall(pattern,page_content)
        for item in res:
            dic={
                'index':item[0],
                'title':item[1],
                'actor':item[2].strip()[3:],
                'time':item[3][5:],
                'score':item[4]+item[5]
    
            }
            print(dic)
    if __name__ == '__main__':
        pattern1=re.compile(r'<dd>.*?board-index.*?>(d+)<.*?title="(.*?)".*?star.*?>(.*?)<.*?releasetime.*?>(.*?)<.*?integer.*?>(.*?)<.*?fraction.*?>(.*?)<',re.S)
    
        url_dic={
            'http://maoyan.com/board/7':pattern1,
        }
    
        p=Pool()
        res_l=[]
        for url,pattern in url_dic.items():
            res=p.apply_async(get_page,args=(url,pattern),callback=parse_page)
            res_l.append(res)
    
        for i in res_l:
            i.get()
    
        # res=requests.get('http://maoyan.com/board/7')
        # print(re.findall(pattern,res.text))

    如果在主进程中等待进程池中所有任务都执行完毕后,再统一处理结果,则无需回调函数

    from multiprocessing import Pool
    import time,random,os
    
    def work(n):
        time.sleep(1)
        return n**2
    if __name__ == '__main__':
        p=Pool()
    
        res_l=[]
        for i in range(10):
            res=p.apply_async(work,args=(i,))
            res_l.append(res)
    
        p.close()
        p.join() #等待进程池中所有进程执行完毕
    
        nums=[]
        for res in res_l:
            nums.append(res.get()) #拿到所有结果
        print(nums) #主进程拿到所有的处理结果,可以在主进程中进行统一进行处理

    进程池的其他实现方式:https://docs.python.org/dev/library/concurrent.futures.html

  • 相关阅读:
    Linux.vim.多行复制、删除、剪切
    Linux.cp命令总提示是否覆盖
    关于常用mysql的文件
    requests 获取百度推广信息
    flask下载文件---文件流
    爬虫---爬虫er与反爬虫er之间的斗争 转发
    爬虫----scrapy账号登录豆瓣,并且重定向到电影界面,获取界面信息
    爬虫----表单登录
    爬虫---爬取豆瓣-科幻片-排行
    爬虫-----爬取所有国家的首都、面积 ,并保存到txt文件中
  • 原文地址:https://www.cnblogs.com/wanghaohao/p/7444827.html
Copyright © 2020-2023  润新知