同步异步

1,同步

  • 同步是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那个这个进程会一直等待下去,直到收到返回信息,才继续执行下去

    from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
    import os, random
    
    
    def task(i):
        print(f'{os.getpid()}开始了任务')
        time.sleep(random.randint(1,3))
        print(f'{os.getpid()}结束了任务')
        return i
    
    
    if __name__ == '__main__':
        p = ProcessPoolExecutor()
        for i in range(10):
            obj = p.submit(task, i)
            print(obj.result())
        p.shutdown(wait=True)

2,异步

  • 是指进程不需要一直等待下去,而是继续执行下面的操作,不管其他进程 的状态,当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率

  • from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
    import os
    import requests
    
    def task(i):
        print(f'{os.getpid()}开始了任务')
        time.sleep(random.randint(1,3))
        print(f'{os.getpid()}结束了任务')
        return i
    
    
    if __name__ == '__main__':
        p = ThreadPoolExecutor()
        li = []
        for i in range(10):
            obj = p.submit(task, i)
            li.append(obj)
        p.shutdown()
        for i in li:
            print(i.result())
    ##################map函数的应用
    if __name__ == '__main__':
        p = ProcessPoolExecutor()
        obj = p.map(task, range(10))
        p.shutdown()
        print(list(obj))

回调函数

  • 进程池与线程池的区别

    • 进程池:主进程调用回调函数,得到任务结果
    • 线程池:空闲线程调用回调函数,得到任务结果
  • 回调函数什么时候用,回调函数在爬虫中最常用,造数据的非常耗时,处理数据的时候不耗时

  • 回调函数的场景:进程池中任何一个任务一旦完成了,就立即告知主进程,主进程则调用一个函数去处理结果,该函数即回调函数。

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

  • 异步加回调函数处理网站

  • from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
    import os
    import requests
    
    
    def url_page(url):
        response = requests.get(url)
        print(f'{os.getpid()} is getting {url}')
        if response.status_code == 200:
            return {"url": url, "text": response.text}
    
    
    def parse_page(res):
        res = res.result()
        with open('url.text', 'a', encoding='utf-8') as f:
            parse_res = f"url:{res['url']} size:{len(res['text'])}"
            f.write(parse_res+'\n')
    
    
    if __name__ == '__main__':
        p = ProcessPoolExecutor(4)
        # p = ThreadPoolExecutor(4)
        l = [
            'http://www.baidu.com',
            'http://www.baidu.com',
            'http://www.baidu.com',
            'http://www.baidu.com',
            'http://www.JD.com',
            'http://www.JD.com',
            'http://www.JD.com',
            'http://www.JD.com',
            'http://www.JD.com',
            'http://www.JD.com',
        ]
        for i in l:
            # res = p.submit(url_page, i).add_done_callback(parse_page)
            ret = p.submit(url_page, i)
            ret.add_done_callback(parse_page)
        p.shutdown()
    
02-13 05:16