在python3.4之后,增加了对异步io的支持,引入了asyncio的模块支持,下面就简单的使用一下asyncio,
1.无回调函数的简单使用:
首先我们先模拟一个请求http的操作,定义一个协程:
#coding=utf-8
import asyncio
async def request_html(url):
print('获取html中')
await asyncio.sleep(2)
print(url)
async是一个关键词,用来定义协程,await asyncio.sleep(2),模拟阻塞2秒,由于属于异步io操作,所以传统的time.sleep(2)的调用会导致同步的等待2秒,比如你使用10个协程去完成异步操作,time.sleep会耗掉10*2秒时间进行操作,使用await asyncio.sleep(2)会耗掉2秒多的时间操作,所以使用了time.sleep就无法享受到异步的好处,然后我们开始主函数里面进行调用
if __name__ == '__main__':
start_time = time.time()
#无回调的使用方法
loop = asyncio.get_event_loop()#我们知道协程的使用是需要在循环体中进行使用的,asyncio里面自定义了loop来进行使用asyncio.get_event_loop()来获取loop。
tasks = [request_html('http') for i in range(10)]#模拟进行10次的请求
loop.run_until_complete(asyncio.wait(tasks))#该方法类型于线程中的join方法,asyncio.wait()可以接受一个可以迭代的对象
print(time.time()-start_time)
然后运行一下,对比一下request_html中使用time.sleep函数跟await asyncio.sleep函数的差别
time.sleep
获取html中
http
获取html中
http
获取html中
http
获取html中
http
20.00114417076111
Process finished with exit code 0
await asyncio.sleep
http
http
http
http
2.0011143684387207
同时根据打印的语句很清楚看出来使用time.sleep并没有使用到多个协程的同步协作,因为每次在sleep之后的操作都是需要等待2秒之后,然后进行打印的,而使用await asyncio.sleep时是在sleep之前先运行完所有的获取html的操作,等过了2秒之后,所有的任务都获取到了http的数据,同时这样提醒了我们在同步阻塞的框架中asyncio是无法使用的,比如Django,flask等,在异步的toranado使用是没有问题的
2.有回调函数的使用
通常我们基本的需求都是需要知道什么时候异常操作结束,以便我们进行下一步操作,所以我们可以定义一个callback函数,我们模拟一个异步调用完发送邮件的操作:
def callback(future):
print('send email')
if __name__ == '__main__':
start_time = time.time()
loop = asyncio.get_event_loop()
task = loop.create_task(request_html('http'))#将协程封装成一个task
task.add_done_callback(callback)#添加一个回调
loop.run_until_complete(task)
print(time.time()-start_time)
然后看到在执行完之后,回调生效,打印了send email的操作
获取html中
http
send email
2.0011143684387207