Python中的协程和异步编程

来源:互联网 发布:高中封闭式管理 知乎 编辑:程序博客网 时间:2024/05/16 14:30

1.什么是协程

协程(coroutine)又被叫做微线程,纤程,是一种用户级的轻量级线程,拥有自己的寄存器和上下文栈,协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来时恢复先前保存的寄存器和上下文栈,因此协程能保留上一次调用时的状态,每次重入过程时,就相当于进入上一次调用的状态,对于CPU来说,协程其实是单线程,所以CPU不用考虑如何调度,切换上下文

2.如何实现协程

python提供的yield关键字可以实现协程,但是比较复杂,用第三方库gevent更方便.
  • 1.使用monkey patching
    gevent对协程的支持,本质上是greenlet在实现切换工作,greenlet工作流程如下:假如进行访问网络的io操作时出现阻塞,greenlet就显示的切换到另一段没有被阻塞的代码执行,直到阻塞情况消失,再自动切换回来
from gevent import monkeyimport geventimport urllib.requestmonkey.patch_all();def run_task(url):  print("正在打开网页:%s"%url)  try:    response = urllib.request.urlopen(url)    data = response.read()    print("从网页%s中一共读取到%d个字节"%(url,len(data)))  except Exception as 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)
  • 使用monkey.pathch_all()方法修改python自带的一些标准库(如io阻塞等)

  • 用spawn方法形成协程,joinall方法添加协程任务,并启动运行

运行结果如下
正在打开网页:https://github.com/
正在打开网页:https://www.python.org/
正在打开网页:http://www.cnblogs.com/
从网页http://www.cnblogs.com/中一共读取到45095个字节
从网页https://www.python.org/中一共读取到48716个字节
从网页https://github.com/中一共读取到56101个字节
可以看出三个网页是并发打开的,而且结束顺序不同

  • 2.使用池
    当拥有动态数量的greenlet需要进行并发管理时,就可以使用池,这在处理大量的网络IO操作时是十分需要的,接下来用gevent中的Pool对象对上面例子进行改写
from gevent import monkeyfrom gevent.pool import Poolimport geventimport urllib.requestmonkey.patch_all()def run_task(url):  try:    response = urllib.request.urlopen(url)    data = response.read()    print("从网页%s中读取到%d个字节"%(url,len(data)))  except Exception as e:    print(e)  return "url:%s ---->结束"%urlif __name__ == "__main__":  pool = Pool(2)  urls = ["https://github.com/","https://www.python.org/","http://www.cnblogs.com/"]  result = pool.map(run_task,urls)  print(result)
  • 结果如下
    从网页https://github.com/中读取到56093个字节
    从网页http://www.cnblogs.com/中读取到45387个字节
    从网页https://www.python.org/中读取到48716个字节
    [‘url:https://github.com/ —->结束’, ‘url:https://www.python.org/ —->结束’, ‘url:http://www.cnblogs.com/ —->结束’]
原创粉丝点击