asyncio
直接内置了对异步IO的支持。
asyncio的编程模型就是一个消息循环。我们从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,就实现了异步IO。
from flask import Flask import time app = Flask(__name__) @app.route('/bobo') def index_bobo(): time.sleep(2) return 'Hello bobo' @app.route('/jay') def index_jay(): time.sleep(2) return 'Hello jay' @app.route('/tom') def index_tom(): time.sleep(2) return 'Hello tom' if __name__ == '__main__': app.run(threaded=True)
async/await的特点
1.async/await更加语义化,async是'异步'的缩写,async function 用于声明一个function是异步的;
await,可以认为是async wait的缩写,用于等待一个异步方法执行完成; 2.async/await是一个用同步思维解决异步问题的方案(等结果出来后代码才会继续执行) 3.可以通过多层async function的同步写法代替传统的callback嵌套
多任务异步爬虫
import asyncio import time import aiohttp #异步请求模块,requests不能异步请求 start = time.time() #在特殊函数内部不可以出现异步模块相关的代码 #注意细节: #1.在每一个with前加上async关键字 #2,在get方法前和response.text()前加上await关键字进行手动挂起操作 async def request(url): async with aiohttp.ClientSession() as s: #s.get/post和request中的get/post用法几乎一样:url,heasers,data/prames #在s.get中如果使用代理:proxy="http://ip:port"是个字符串,而requests中是个字典 async with await s.get(url) as response: #有阻塞的地方加上await,手动挂起 # 获取字符串形式的响应数据:response.text() # 获取byte类型的:response.read() page_text=await response.text() return page_text urls=[] for i in range(500): urls.append('http://127.0.0.1:5000/bobo') def back(task): #接收执行任务的对象 page_text=task.result() #任务对象.result()获得任务函数的返回值 print(page_text) tasks=[] for url in urls: c=request(url) task=asyncio.ensure_future(c) #创建任务对象 task.add_done_callback(back) #添加回调函数,在任务执行完会执行回调函数,可以进行数据分析 tasks.append(task)#将任务添加到任务列表中 loop=asyncio.get_event_loop() #创建事件循环对象 loop.run_until_complete(asyncio.wait(tasks)) #将任务对象注册到该对象中,并且启动时间循环,加上挂起操作,否则会导致阻塞 print(time.time()-start)
----------------
3.090151786804199
#500个请求只需3秒,而每个请求还有2秒的io
清风徐来.水波不兴