学Python不得不掌握的库,gevent和asyncio使用方法详解

一、gevent

python程序实现的一种单线程下的多任务执行调度器,简单来说在一个线程里,先后执行AB两个任务,但是当A遇到耗时操作(网络等待、文件读写等),这个时候gevent会让A继续执行,但是同时也会开始执行B任务,如果B在遇到耗时操作同时A又执行完了耗时操作,gevent又继续执行A。

使用示例:

其中gevent.sleep()是gevent自带的延时,当gevent遇到这个延时时会自动切换,这里用gevent.sleep()代替一些耗时操作,如数据库的读写、http请求、文件度写等操作,gevent给我们提供了一个很简单的协程操作。

二、asyncio

asyncio的使用上,感觉和gevent有异曲同工之妙

1、基础概念:

event_loop事件循环:理解为一个循环的池,里面存放一些async关键词定义的协程函数,只有放到循环池里才能执行

coroutine协程:协程对象,指一个使用async关键字定义的函数,它的调用不会立即执行函数,而是会返回一个协程对象。协程对象需要注册到事件循环,由事件循环调用。

task任务:一个协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,其中包含任务的各种状态。

future:代表将来执行或没有执行的任务的结果。它和task上没有本质的区别

async/await关键字:python3.5 用于定义协程的关键字,async定义一个协程,await用于挂起阻塞的异步调用接口。

2、创建task

协程对象不能直接运行,需要包装成任务才能运行,上面是通过run_until_complete()方法包装成task(隐式包装),还有下面两种方式进行显式包装:

创建task后,task在加入事件循环之前是pending状态,加入loop后运行中是running状态,loop调用完是Done,运行完是finished状态,虽说本质上协程函数和task指的东西都一样,但是task有了协程函数的状态。

其中loop.run_until_complete()接受一个future参数,futurn具体指代一个协程函数,而task是future的子类,所以我们不声明一个task直接传入协程函数也能执行。

3、绑定回调函数

通过task的task.add_done_callback(callback)方法绑定回调函数,回调函数接收一个future对象参数如task,在内部通过future.result()获得协程函数的返回值。

4、await(挂起耗时操作)

多任务声明了协程函数,也同时在loop中注册了,他的执行也是顺序执行的,因为在异步函数中没有声明那些操作是耗时操作,所以会顺序执行。await的作用就是告诉控制器这个步骤是耗时的,async可以定义协程对象,使用await可以针对耗时的操作进行挂起

上面执行并不是异步执行,而是顺序执行,但是改成下面形式那就是异步执行:

可见三个任务的间隔时间几乎忽略不计,这里要注意可以使用await成功挂起的对应应该是下面三种:

原生异步函数(coroutine)

由 types.coroutine() 修饰的生成器,这个生成器可以返回 coroutine 对象。

包含 __await 方法的对象返回的一个迭代器

所以即使使用saync修饰requests的方法也不支持异步,而是需要专门的异步网络请求库aiohttp。

5、aiohttp

aiohttp需要单独安装,然后和asyncio库一起使用,看一下案例

几个任务的时间之差基本忽略不计,那亲测发送一千个请求也就11秒完成,确实很给力。

6、多进程配合使用

asyncio、aiohttp需要配合aiomultiprocess库使用,版本要求至少3.6,贴上该库的github上的使用示例,目前还在验证:

7、多协程并发

使用loop.run_until_complete(syncio.wait(tasks)) 也可以使用 loop.run_until_complete(asyncio.gather(*tasks)) ,前者传入task列表,会对task进行解包操作。

7、协程嵌套

顾名思义是一个协程中调用另一个协程,但是涉及到两个协程函数的结果处理和返回。

被调用协程返回结果有下列三种方式;

8、停止协程任务

实现结束task有两种方式:关闭单个task、关闭loop,涉及主要函数:

asyncio.Task.all_tasks()获取事件循环任务列表

KeyboardInterrupt捕获停止异常(Ctrl+C)

loop.stop()停止任务循环

task.cancel()取消单个任务

loop.run_forever()

loop.close()关闭事件循环,不然会重启

------------------------------

ID:Python之战

|作|者|公(zhong)号:python之战

专注Python,专注于网络爬虫、RPA的学习-践行-总结

喜欢研究技术瓶颈并分享,欢迎围观,共同学习。

独学而无友,则孤陋而寡闻!

---------------------------

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190111A16PZM00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券