基于python生成器封装的协程类


Posted in Python onMarch 20, 2019

自从python2.2提供了yield关键字之后,python的生成器的很大一部分用途就是可以用来构建协同程序,能够将函数挂起返回中间值并能从上次离开的地方继续执行。python2.5的时候,这种生成器更加接近完全的协程,因为提供了将值和异常传递回到一个继续执行的函数中,当等待生成器的时候,生成器能返回控制。

python提供的生成器设施:

  • yield:能够将自己挂起,并提供一个返回值给等待方
  • send:唤起一个被挂起的生成器,并能够传递一个参数,可以在生成器中抛出异常
  • next:本质上相当于send(None),对每个生成器的第一次调用必须不能传递参数
  • close:主动退出一个生成器

python封装

虽然python3提供了asyncio这样的异步IO库,而且也有greenlet等其他协程库,但目前的需求并不是实际的网络IO并发操作,而是需要模拟状态机的运行,因此使用协程可以很方便的模拟,并加入认为的控制,下面是封装的一个python类。

class Coroutine(object):

  """ Base class of the general coroutine object """

  STATE_RUNNING = 0
  STATE_WAITING = 1
  STATE_CLOSING = 2

  def __init__(self):
    self.state = Coroutine.STATE_WAITING
    self.started = False
    self.args = None
    self.routine = self._co()

  def _co(self):
    self.ret = None
    while True:
      self.args = yield self.ret
      if not self.started:
        self.started = True
        continue
      else:
        self.state = Coroutine.STATE_RUNNING
        self.ret = self.run(self.args)
      if self.state == Coroutine.STATE_CLOSING:
        break
      self.state = Coroutine.STATE_WAITING

  def start(self):
    """ Start the generator """
    if self.routine is None:
      raise RuntimeError('NO task to start running!')
    self.started = True
    self.routine.next()

  def finish(self):
    """ Finish the execution of this routine """
    self.state = Coroutine.STATE_CLOSING
    self.routine.close()

  def run(self, args):
    """ The runing method to be executed every once time"""
    raise NotImplementedError

  def execute(self, arg_obj):
    """ Awake this routine to execute once time """
    return self.routine.send(arg_obj)

基于上述封装,下面实现了一个协同的生产者消费者示例:

class ProducerCoroutine(Coroutine):

  """ The Producer concrete coroutine """

  def __init__(self, cnsmr):
    if not isinstance(cnsmr, Coroutine):
      raise RuntimeError('Consumer is not a Coroutine object')
    self.consumer = cnsmr
    self.consumer.start()
    super(ProducerCoroutine, self).__init__()

  def run(self, args):
    print 'produce ', args
    ret = self.consumer.execute(args)
    print 'consumer return:', ret

  def __call__(self, args):
    """ Custom method for the specific logic """
    self.start()
    while len(args) > 0:
      p = args.pop()
      self.execute(p)
    self.finish()


class ConsumerCoroutine(Coroutine):

  """ The Consumer concrete coroutine """

  def __init__(self):
    super(ConsumerCoroutine, self).__init__()

  def run(self, args):
    print 'consumer get args: ', args
    return 'hahaha' + repr(args)

运行结果如下:

produce 4
consumer get args: 4
consumer return: hahaha4
produce 3
consumer get args: 3
consumer return: hahaha3
produce 2
consumer get args: 2
consumer return: hahaha2
produce 1
consumer get args: 1
consumer return: hahaha1
produce 0
consumer get args: 0
consumer return: hahaha0

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python对象及面向对象技术详解
Jul 19 Python
Python中的sort()方法使用基础教程
Jan 08 Python
Python cookbook(数据结构与算法)保存最后N个元素的方法
Feb 13 Python
python 信息同时输出到控制台与文件的实例讲解
May 11 Python
python实现人人自动回复、抢沙发功能
Jun 08 Python
django的ORM操作 增加和查询
Jul 26 Python
基于django传递数据到后端的例子
Aug 16 Python
python操作cfg配置文件方式
Dec 22 Python
Jupyter打开图形界面并画出正弦函数图像实例
Apr 24 Python
使用keras时input_shape的维度表示问题说明
Jun 29 Python
使用PyWeChatSpy自动回复微信拍一拍功能的实现代码
Jul 02 Python
记一次django内存异常排查及解决方法
Aug 07 Python
python实现栅栏加解密 支持密钥加密
Mar 20 #Python
python实现Virginia无密钥解密
Mar 20 #Python
python实现维吉尼亚加密法
Mar 20 #Python
Python multiprocess pool模块报错pickling error问题解决方法分析
Mar 20 #Python
python实现对输入的密文加密
Mar 20 #Python
python实现字符串加密成纯数字
Mar 19 #Python
python实现简单加密解密机制
Mar 19 #Python
You might like
PHP 处理图片的类实现代码
2009/10/23 PHP
pdo中使用参数化查询sql
2011/08/11 PHP
PHP5常用函数列表(分享)
2013/06/07 PHP
PHP重定向与伪静态区别
2017/02/19 PHP
Thinkphp结合ajaxFileUpload实现异步图片传输示例
2017/03/13 PHP
PHP检查网站是否宕机的方法示例
2017/07/24 PHP
PHP使用函数用法详解
2018/09/30 PHP
ext for eclipse插件安装方法
2008/04/27 Javascript
JS编程小常识很有用
2012/11/26 Javascript
jquery.ajax的url中传递中文乱码问题的解决方法
2014/02/07 Javascript
Jquery实现自定义窗口随意的拖拽
2014/03/12 Javascript
自定义jquery模态窗口插件无法在顶层窗口显示问题
2014/05/29 Javascript
node.js中的fs.mkdirSync方法使用说明
2014/12/17 Javascript
jquery实现搜索框常见效果的方法
2015/01/22 Javascript
JavaScript动态加载样式表的方法
2015/03/21 Javascript
jQuery无刷新分页完整实例代码
2015/10/27 Javascript
vue2.0 computed 计算list循环后累加值的实例
2018/03/07 Javascript
如何把vuejs打包出来的文件整合到springboot里
2018/07/26 Javascript
vue学习笔记五:在vue项目里面使用引入公共方法详解
2019/04/04 Javascript
JS使用for in有序获取对象数据
2020/05/19 Javascript
nestjs中异常过滤器Exceptionfilter的具体使用
2021/02/07 Javascript
[42:25]2018DOTA2亚洲邀请赛 4.5 淘汰赛 LGD vs Liquid 第三场
2018/04/06 DOTA
django 在原有表格添加或删除字段的实例
2018/05/27 Python
Python使用wget实现下载网络文件功能示例
2018/05/31 Python
python钉钉机器人运维脚本监控实例
2019/02/20 Python
python 伯努利分布详解
2020/02/25 Python
python代码如何注释
2020/06/01 Python
HTML5 拖放(Drag 和 Drop)详解与实例代码
2017/09/14 HTML / CSS
俄罗斯电子产品、计算机和家用电器购物网站:OLDI
2019/10/27 全球购物
十佳教师事迹材料
2014/01/11 职场文书
绿色城市实施方案
2014/03/19 职场文书
小学优秀辅导员事迹材料
2014/05/11 职场文书
本溪水洞导游词
2015/02/11 职场文书
教务处教学工作总结
2015/08/10 职场文书
Redis模仿手机验证码发送的实现示例
2021/11/02 Redis
Java结构型设计模式之组合模式详解
2022/09/23 Java/Android