zoukankan      html  css  js  c++  java
  • (十)异步调用与回调机制

    一、同步调用


    提交任务有两种方式:同步调用,异步调用。

    同步调用:提交完任务后,就在原地等待任务执行完毕,拿到结果再执行下一行代码,导致程序是串行执行。

    例子:今年你们公司开年会,举办了一个吃汉堡大赛,然后把计算下大家一共吃了多少个,谁的最多,谁发的年终奖就最多。

    # 1,同步调用:提交完任务后,就在原地等待任务执行完毕,拿到结果再执行下一行代码,导致程序是串行执行。
    from concurrent.futures import ThreadPoolExecutor
    import time,random
    
    def eat(name):
        print("%s 正在吃。" % name)
        time.sleep(random.randint(3,5))     # 吃的时间
        res = random.randint(7,13)          # 吃了几个
        return {"name":name,"res":res}
    
    def count(hamburger):
        name = hamburger["name"]
        num = hamburger["res"]
        print("%s 吃了《%s》个。" % (name,num))
    
    if __name__ == '__main__':
        pool = ThreadPoolExecutor(3)    # 参赛人数,用线程池
    
        shit1 = pool.submit(eat,"托儿所").result()   # 提交任务,等待任务执行完毕,拿到结果
        count(shit1)
        shit2 = pool.submit(eat,"儿童劫").result()
        count(shit2)
        shit3 = pool.submit(eat,"瑞萌萌").result()
        count(shit3)
    
    """
    托儿所 正在吃。
    托儿所 吃了《8》个。
    儿童劫 正在吃。
    儿童劫 吃了《12》个。
    瑞萌萌 正在吃。
    瑞萌萌 吃了《8》个。
    """

    二、异步调用与回调函数


    异步调用:提交完任务后,不在原地等待任务执行完毕。

    回调函数:可以为进程池或线程池内的每个进程或线程绑定一个函数,该函数在进程或线程的任务执行完毕后自动触发,并接收任务的返回值当作参数,该函数称为回调函数。

    # 2,异步调用:提交完任务后,不在原地等待任务执行完毕,
    from concurrent.futures import ThreadPoolExecutor
    import time,random
    
    def eat(name):
        print("%s 正在吃。" % name)
        time.sleep(random.randint(3,5))     # 吃的时间
        res = random.randint(7,13)          # 吃几个
        return {"name":name,"res":res}
        # weight({"name":name,"res":res})   # 这样写的话,相当于把两个函数写到一起了,耦合了,而我们是要解耦合的
    
    def count(hamburger):
        hamburger = hamburger.result()    # 这里的hamburger拿到的是一个对象
        name = hamburger["name"]
        num = hamburger["res"]
        print("%s 吃了《%s》个." % (name,num))
    
    if __name__ == '__main__':
        pool = ThreadPoolExecutor(3)    # 参赛人数,用线程池
    
        # 回调函数是在,前面的函数执行完,有返回值了,自动触发这个功能,把前面的对象直接当参数传给weight
        pool.submit(eat,"托儿所").add_done_callback(count)     # 前面是对象,后面的是回调函数
        pool.submit(eat,"儿童劫").add_done_callback(count)
        pool.submit(eat,"瑞萌萌").add_done_callback(count)
        # count拿到的是一个future对象obj,需要用obj.result()拿到结果,也就是 hamburger.result()
    
    """
    托儿所 正在吃。
    儿童劫 正在吃。
    瑞萌萌 正在吃。
    瑞萌萌 吃了《12》个.
    托儿所 吃了《12》个.
    儿童劫 吃了《11》个.
    """

    三、练习


    在程序当中模拟浏览器的行为

    from concurrent.futures import ThreadPoolExecutor
    import requests     # 在程序当中模拟浏览器的行为,要用到这个模块
    import time
    
    def get(url):
        print("GET %s." % url)
        # requests.get 实际上就是去目标站,下载一个文件到本地
        response = requests.get(url)    # 传上你的额 url地址,它会拿到一个对象
        time.sleep(3)
        return {"url":url,"content":response.text}      # text这个属性得到的是网页内容
    
    def parse(res):
        """解析网页信息"""
        # 正则表达式,解析出你想要的内容
        # 爬虫项目基本原理:先把内容(字符串)下载下来,再对内容进行处理得到自己想要的部分。
        res = res.result()
        print("%s parse res is %s." % (res["url"],len(res["content"])))
    
    
    if __name__ == '__main__':
        urls = [
            "https://www.cnblogs.com/zoling7",
            "https://www.baidu.com",
            "https://www.huya.com",
        ]
    
        pool = ThreadPoolExecutor(2)
    
        for url in urls:
            pool.submit(get,url).add_done_callback(parse)
    
    """
    GET https://www.cnblogs.com/zoling7.
    GET https://www.baidu.com.
    https://www.baidu.com parse res is 2443.
    GET https://www.huya.com.
    https://www.cnblogs.com/zoling7 parse res is 15181.
    https://www.huya.com parse res is 397258.
    """
  • 相关阅读:
    hdu 4710 Balls Rearrangement()
    hdu 4707 Pet(DFS水过)
    hdu 4706 Children's Day(模拟)
    hdu 4712 Hamming Distance(随机函数暴力)
    csu 1305 Substring (后缀数组)
    csu 1306 Manor(优先队列)
    csu 1312 榜单(模拟题)
    csu 1303 Decimal (数论题)
    网络爬虫
    Python处理微信利器——itchat
  • 原文地址:https://www.cnblogs.com/zoling7/p/13397494.html
Copyright © 2011-2022 走看看