异步回调--day36
"""
----异步回调----
异步任务使用场景
爬虫
1.从目标站点下载网页数据 本质就是HTML格式字符串
2.用re从字符串中提取出你需要的数据
什么是回调(函数)
a 交给 b一个任务 b在执行完成后回过头调用了a的一个函数 就称之为回调
为什么需要回调函数?
需要获取异步任务的结果,但是又不应该阻塞(降低效率)
高效的获取任务结果
(像生产者与消费者,生产者生产了产品后,通知消费者过来消费,消费者不需要一直等待生产者)
通常异步任务都会和回调函数一起使用
使用方式:
使用add_done_callback函数()给Future对象绑定一个回调函数
注意:在多进程中回调函数 是交给主进程来执行 而在多线程中 回调函数是谁有空谁执行(不是主线程)
"""
#-----进程中使用异步回调来处理结果---- import requests, re, os from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor from threading import current_thread # 请求下载一个网业的数据 response = requests.get("https://www.baidu.com") # 下载网站的数据,转换格式 htm = response.content.decode("utf-8") # 用正则表达式取出网页里面的所有链接 # print(re.findall("href=.*?com",htm)) def get_data(url): print("%s 正在请求%s" % (os.getpid(), url)) # 下载网址的内容 response = requests.get(url) print("%s 请求%s成功" % (os.getpid(), url)) # 返回出去----1 return response def parser(obj): # 获得上一段代码的返回值 res = obj.result() htm = res.content.decode("utf-8") ls = re.findall("href=.*?com", htm) print("%s解析完成! 共%s个连接" % (os.getpid(), len(ls))) # 不加报错 if __name__ == '__main__': urls = ["https://www.baidu.com", "https://www.sina.com", "https://www.tmall.com", "https://www.taobao.com", "https://www.jd.com", "https://www.python.org", "https://www.apple.com"] # 用一个进程池 来开启进程 pool = ProcessPoolExecutor(3) for i in urls: # 循环取出urls 中的网址 交给进程池 得到执行完后的返回值 obj = pool.submit(get_data, i) # res = obj.result() # 会把任务变成串行 # parser(res) # 上一段代码执行完成后 会得到通知,继续执行下一段代码 obj.add_done_callback(parser)
# ----线程池中使用异步回调---- import requests, re, os from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor from threading import current_thread def get_data(url): # current_thread().name 获取执行线程的名字 print("%s 正在请求%s" % (current_thread().name, url)) response = requests.get(url) print("%s 请求%s成功" % (current_thread().name, url)) return response def parser(obj): res = obj.result() htm = res.content.decode("utf-8") ls = re.findall("href=.*?com", htm) print("%s解析完成! 共%s个连接" % (current_thread().name,len(ls))) if __name__ == '__main__': urls = ["https://www.baidu.com", "https://www.tmall.com", "https://www.taobao.com", "https://www.jd.com", "https://www.python.org", "https://www.apple.com"] pool = ThreadPoolExecutor(3) for i in urls: # 循环取出urls 中的网址 交给线程池 得到执行完后的返回值 obj = pool.submit(get_data, i) # res = obj.result() # 会把任务变成串行 # parser(res) # 上一段代码执行完成后 会得到通知,继续执行下一段代码 obj.add_done_callback(parser)