#coding:utf-8-*- '''协程(coroutine)又称微线程、纤程,是一种用户级的轻量级线程。协程有本身的寄存器上下文和栈。携程调度时,将寄存器上下文和栈 保存,在切换回来的时候恢复保存的寄存器上下文和栈。因此每次重入时,就至关于进入上一次的调用状态,在并发编程中协程与线程相似,每一个协 程标识一个执行单元有本身的本地数据与其余协程共享全局数据和资源。 协程须要用户自行编写调度逻辑,对CPU来说协程是单线程的,因此CPU不用考虑怎么调度、切换上下文节约CPU开销,因此协程在必定程度上 又优于多线程。 python在默认提供了yield对协程进行基本的支持,但不彻底,建议使用第三方库:gevent,其提供了比较完善的协程支持。 gevent对协程的支持,本质上来说是greenlet在实现切换工做,greenlet的工做流程以下: ---加入IO操做出现阻塞,greenlet就显示的切换到另外一端没有被阻塞的代码段执行,指导原先的阻塞状态消失,在切换回原来的代码段 继续执行。 gevent为咱们自动切换协程就保证了总有greenlet在运行而不是等待IO操做,这就是协程比多线程效率高的缘由''' #gevent的使用 # from gevent import monkey # # from gevent import monkey.patch_all # import gevent # import urllib2 # from idlelib.rpc import response_queue # from greenlet import greenlet # def run_task(url): # print("Visit-->%s"%url) # try: # response=urllib2.urlopen(url) # date=response.read() # print('%d bytes received from %s' %(len(date),url)) # except Exception as e: # print(e) # if __name__=="__main__": # urls=['https://github.com/','https://www.python.org/','http://cnblogs.com/'] # greenlets=[gevent.spawn(run_task,url)for url in urls] # gevent.joinall(greenlets) #以上主要使用了gevent中的spawn方法和joinall方法, spawn用来造成协程,joinall方法用来添加这些任务并启动 #以上三个网络操做是并发执行的而结束顺序不一样,但实际只有一个线程 #------------------------------------------------------------------------------------- #使用gevent的pool对象进行动态数量的greenlent并发管理 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 bytes reveived from %s.' %(len(data),url)) except Exception as 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) #以上程序中Pool对象对协程的并发数量进行了管理,先访问了前两个网址,当其中一个任务完成时才会访问第三个