谁说Python协程是鸡肋的!站出来我不打死他!这…

2018-08-10 11:27:24来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

谁说Python协程是鸡肋的!站出来我不打死他!这么牛逼的协程!

 

文章思路:本文将先介绍协程的概念,然后分别介绍Python2.x与3.x下协程的用法,最终将协程与多线程做比较并介绍异步爬虫模块。

协程

概念

协程,又称微线程,纤程,英文名Coroutine。协程的作用,是在执行函数A时,可以随时中断,去执行函数B,然后中断继续执行函数A(可以自由切换)。但这一过程并不是函数调用(没有调用语句),这一整个过程看似像多线程,然而协程只有一个线程执行。

进群:548377875   即可获取数十套PDF哦!

谁说Python协程是鸡肋的!站出来我不打死他!这么牛逼的协程!

 

Python2.x协程

谁说Python协程是鸡肋的!站出来我不打死他!这么牛逼的协程!

 

python2.x协程应用:

  • yield
  • gevent

python2.x中支持协程的模块不多,gevent算是比较常用的,这里就简单介绍一下gevent的用法。

Gevent

gevent是第三方库,通过greenlet实现协程,其基本思想:

当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。

谁说Python协程是鸡肋的!站出来我不打死他!这么牛逼的协程!

 

运行结果:

start 0

start 1

start 2

end 2

end 0

end 1

说明:从结果上来看,执行get_body的顺序应该先是输出”start”,然后执行到urllib2时碰到IO堵塞,则会自动切换运行下一个程序(继续执行get_body输出start),直到urllib2返回结果,再执行end。也就是说,程序没有等待urllib2请求网站返回结果,而是直接先跳过了,等待执行完毕再回来获取返回值。值得一提的是,在此过程中,只有一个线程在执行,因此这与多线程的概念是不一样的。

谁说Python协程是鸡肋的!站出来我不打死他!这么牛逼的协程!

 

Gevent使用说明

  • monkey可以使一些阻塞的模块变得不阻塞,机制:遇到IO操作则自动切换,手动切换可以用gevent.sleep(0)(将爬虫代码换成这个,效果一样可以达到切换上下文)
  • gevent.spawn 启动协程,参数为函数名称,参数名称
  • gevent.joinall 停止协程

Python3.x协程

为了测试Python3.x下的协程应用,我在virtualenv下安装了python3.6的环境。

python3.x协程应用:

  • asynico + yield from(python3.4)
  • asynico + await(python3.5)
  • gevent

Python3.4以后引入了asyncio模块,可以很好的支持协程。

asynico

asyncio是Python 3.4版本引入的标准库,直接内置了对异步IO的支持。asyncio的异步操作,需要在coroutine中通过yield from完成。

谁说Python协程是鸡肋的!站出来我不打死他!这么牛逼的协程!

 

说明:从运行结果可以看到,跟gevent达到的效果一样,也是在遇到IO操作时进行切换(所以先输出test_1,等test_1输出完再输出test_2)。但此处我有一点不明,test_1的输出为什么不是按照顺序执行的呢?可以对比gevent的输出结果(希望大神能解答一下)。

谁说Python协程是鸡肋的!站出来我不打死他!这么牛逼的协程!

 

Usage

例子(python3.5以后版本使用):

谁说Python协程是鸡肋的!站出来我不打死他!这么牛逼的协程!

 

gevent

同python2.x用法一样。

协程VS多线程

如果通过以上介绍,你已经明白多线程与协程的不同之处,那么我想测试也就没有必要了。因为当线程越来越多时,多线程主要的开销花费在线程切换上,而协程是在一个线程内切换的,因此开销小很多,这也许就是两者性能的根本差异之处吧。(个人观点)

异步爬虫

也许关心协程的朋友,大部分是用其写爬虫(因为协程能很好的解决IO阻塞问题),然而我发现常用的urllib、requests无法与asyncio结合使用,可能是因为爬虫模块本身是同步的(也可能是我没找到用法)。那么对于异步爬虫的需求,又该怎么使用协程呢?或者说怎么编写异步爬虫?

  • grequests (requests模块的异步化)
  • 爬虫模块+gevent(比较推荐这个)
  • aiohttp (这个貌似资料不多,目前我也不太会用)
  • asyncio内置爬虫功能 (这个也比较难用)

协程池

作用:控制协程数量

谁说Python协程是鸡肋的!站出来我不打死他!这么牛逼的协程!

 

get去吧!

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:常用内置模块——time、os、sys、random、shutil、pickle、json

下一篇:python基础的一些知识点