Python之——协程

转载请注明出处:https://blog.csdn.net/l1028386804/article/details/83042357

协程(coroutine),又称微线程,是一种用户级的轻量级线程。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此协程保留上一次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态。在并发编程中,协程与线程类似,每个协程表示一个执行单元,有自己的本地数据,与其他协程共享全局数据和其他资源。
协程需要用户自己来编写调度逻辑,对于CPU来说,协程其实是单线程,所以CPU不用去考虑怎么调度、切换上下文,这就省去了CPU的切换开销,所以协程在一定程度上又好于多线程。那么在Python中是如何实现协程的呢?
Python通过yield提供了对协程的基本支持,但是不完全,而使用第三方gevent库是更好的选择,gevent提供了比较完善的协程支持,是一个基于协程的Python网络函数库,使用greenlet在libenv事件循环顶部提供了一个高级别并发性的API。
gevent对协程的支持,本质上是greenlet在实现切换工作。greenlet工作流程如下:假如进行访问网络的IO操作时,出现阻塞,greenlet就显示切换到另一段没有被阻塞的代码执行,直到原先的阻塞状况消失后,再自动切换回原来的代码继续处理。因此,greenlet是一种合理安排的串行方式。
gevent使用流程代码如下:

# -*- coding:UTF-8 -*-

from gevent import monkey; monkey.patch_all()
import gevent
import urllib2

def run_task(url):
	print 'Visit --> %s' % url
	try:
		response = urllib2.urlopen(url)
		data = response.read()
		print '%d bytes received from %s.' % (len(data), url)
	except Exception, e:
		print e

if __name__ == '__main__':
	urls = ['https://github.com', 'https://www.python.org', 'http://www.cnblogs.com']
	greenlets = [gevent.spawn(run_task, url) for url in urls]
	gevent.joinall(greenlets)

以上程序主要用了gevent中的spawn方法和joinall方法。spawn方法可以看做是用来形成协程,joinall方法就是添加这些协程任务,并且启动运行,从运行结果来看,3个网络操作是并发执行的,而且结束顺序不同,但其实只有一个线程。

gevent中还提供了对池的支持。当拥有动态数量的greenlet需要进行并发管理(限制并发数)时,就可以使用池,这在处理大量的网路和IO操作时是非常需要的,接下来使用gevent中pool对象,来实现gevent操作。

示例代码如下:

# -*- coding:UTF-8 -*-
from gevent import monkey; monkey.patch_all()
import urllib2
from gevent.pool import Pool

def run_task(url):
	print 'Visit --> %s' % url
	try:
		response = urllib2.urlopen(url)
		data = response.read()
		print '%d biyes received from %s.' % (len(data), url)
	except Exception, e:
		print e
	return 'url:%s ---> finish' % url

if __name__ == '__main__':
	pool = Pool(2)
	urls = ['https://github.com', 'https://www.python.org', 'http://www.cnblogs.com']
	results = pool.map(run_task, urls)
	print results

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰 河

可以吃鸡腿么?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值