asyncio
asyncio是 Python 3.4 中引入的标准库,直接内置了对异步IO的支持。
asyncio 的编程模型就是一个消息循环,从 asyncio 模块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,就实现了异步IO。
下面是来自于 Python 官方文档的例子(请使用 Python3.4 运行),我对它做了一点修改,增加了 2个任务,方便更好地理解 链接>>>
|
|
如果是一个任务,就是下面的情况:
@asyncio.coroutine把一个generator标记为coroutine类型,然后把这个coroutine扔到EventLoop中执行。
yield from语法可以让我们方便地调用另一个generator。由于asyncio.sleep()也是一个coroutine,所以线程不会等待asyncio.sleep(),而是直接中断并执行下一个消息循环。当asyncio.sleep()返回时,线程就可以从yield from拿到返回值return x + y,然后接着执行下一行语句print("%s + %s = %s" % (x, y, result))
把asyncio.sleep(2.0)看成是一个耗时1秒的IO操作,在此期间,主线程并未等待,而是去执行EventLoop中其他可以执行的coroutine了,因此可以实现并发执行。
aiohttp
asyncio可以实现单线程并发IO操作,它实现了TCP、UDP、SSL 等协议;aiohttp则是基于asyncio实现的 HTTP 框架,使用它可以实现高并发的 HTTP 请求。
由于 aiohttp 是第三方库,使用前先安装:
|
|
先看一下 aiohttp 官网的例子(请使用 Python 3.5+ 运行),官网链接>>>
|
|
由于我用的装的是 Python 3.4 ,对它稍作修改即可,修改方式参见官网 Note
|
|
修改后
|
|
异步 IO
因为之前写过一个图片爬虫,明显是属于网络 IO 型的应用,如果用异步的方式来爬取图片会如何?
下面直接看代码:
|
|
由于异步用在 IO 这种耗时的操作才有意义,因此只需对程序中涉及到网络通信的部分重写。
爬虫运行的流程:
爬虫先获取页面的 HTML 文件get_html() —> 解析文件中的图片链接 —> 用图片链接直接获取图片文件download_picture() —> 保存图片
使用异步后,爬取图片的效率提升相当的明显,以前下载 50 个页面大约耗时 30 分钟,现在 1 分钟内就能下完,有兴趣的朋友可以试试。
项目地址
文件名:meizitu_asynchronous.py