Python3异步编程

Posted 点融黑帮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python3异步编程相关的知识,希望对你有一定的参考价值。

Python3.4之后引入asyncio标准库,并在3.5中提供原生语法支持,为编写异步程序提供了高效且优雅的方法。对于编写爬虫和httpserver的这类IO密集型应用,asyncio的表现非常亮眼。

asyncio基于协程实现,至于为什么不用进程or线程实现并发,忽略内核陷入开销以及GIL,进程与线程依赖操作系统调度,调度开销高,调度方式也不一定与应用适配。


Coroutine协程
Python3异步编程


协程是可以暂停和恢复的用户态“线程”。但协程的定义并不十分明确,也有多种实现。但总的来讲都是基于生成器,所以为了理解协程,先简单介绍一下python生成器:

1.栈帧PyFrameObject保存代码的信息和上下文

2.栈帧拥有自己的数据栈和block栈,解释器可以中断和恢复栈帧

3.python将函数编译成字节码时,碰到yield语句,标记它为生成器函数

4.程序调用生成器函数时,python创建生成器对象

5.所有调用特定生成器函数得到的生成器对象都指向同样的代码。但每个生成器对象都有独立的栈帧

6.调用send或next方法,由gen_send_ex函数执行系列操作、修改生成器状态,然后调用PyEval_EvalFrameEx执行字节码(如果代码块为空或调用栈为空,抛出StopIteration异常)


EventLoop 事件循环
Python3异步编程


事件循环是asyncio的核心,它负责:


1.注册、执行以及取消超时调用

2.为各种通信创建client和server通道

3.启动子程序和并创建与外部程序通信的通道

4.将耗时任务委托给线程池


获取事件循环:


asyncio.get_event_loop_policy获取事件循环策略,asyncio.get_event_loop获取事件循环.


设置事件循环:


asyncio.set_event_loop_policy设置事件循环策略,asyncio.set_event_loop设置事件循环


以uvloop为例:

Python3异步编程


输出:

Python3异步编程


开启事件循环:


AbstractEventLoop.run_forever开启事件循环直到stop方法被调用

AbstractEventLoop.run_until_complete开启事件循环,如果参数是协程对象,ensure_future会将协程封装为Task。函数返回Futures的结果或者抛出相应的异常。


关闭事件循环:


AbstractEventLoop.stop如果run_forever正在运行,对当前批次执行callback后退出。

run_forever再次被调用时,继续执行。

AbstractEventLoop.close强制关闭事件循环,抛弃待处理的回调。并且关闭之后不可逆转。


Future
Python3异步编程


封装callable的异步执行,Task的基类,非线程安全。


Task任务
Python3异步编程


Task是Future的子类,负责在事件循环中执行协程。事件循环同一时间只执行一个task(其他线程中的任务可能可以“并行”)。当task等待其他future完成时,事件循环执行新的task(并发)。

使用asyncio.ensure_future函数或者AbstractEventLoop.create_task方法创建task,Task非线程安全。

对于非线程安全问题,一个event_loop只在一个线程中运行,所以只需要担心event_loop之外的情况,asyncio.run_coroutine_threadsafe与loop.call_soon_threadsafe可以应对。


Crawler
Python3异步编程


接下来我们基于asyncio和aiohttp编写一个爬虫抓取豆瓣电影top250(隐去异常处理,下同):

Python3异步编程

COSTTIME: 0.25513544082641604S


线程池版本:

Python3异步编程

COSTTIME: 0.4078077793121338 S


这个对比虽不够严谨,但也可以看出asyncio的异步性能,特别是在并发量越来越大的时候,python可以轻松开启上万的协程,而开启上万线程操作系统可能会不堪重负。


结语
Python3异步编程


上面我们介绍了协程和asyncio标准库,并编写了一个简单的网络爬虫,对比协程和多线程版本。实际上对于HTTPSERVER,Sanic+uvloop能创造出惊人的性能,详见uvloop:Blazing fast Python networking

https://magic.io/blog/uvloop-blazing-fast-python-networking/)



Python3异步编程


Python3异步编程


点击回顾往期精彩内容


















以上是关于Python3异步编程的主要内容,如果未能解决你的问题,请参考以下文章

Python3 asyncio异步编程介绍

python 异步编程

python3异步爬虫:asyncio + aiohttp + aiofiles(python经典编程案例)

python 异步编程

异步编程Async/await关键字

python异步编程之asyncio(百万并发)