基于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 测试实现方法
Dec 24 Python
pymongo给mongodb创建索引的简单实现方法
May 06 Python
简单了解Python下用于监视文件系统的pyinotify包
Nov 13 Python
详解在Python程序中解析并修改XML内容的方法
Nov 16 Python
浅谈Python2.6和Python3.0中八进制数字表示的区别
Apr 28 Python
Python实现购物车购物小程序
Apr 18 Python
python2.x实现人民币转大写人民币
Jun 20 Python
pyqt5 QScrollArea设置在自定义侧(任何位置)
Sep 25 Python
Python实现把多维数组展开成DataFrame
Nov 30 Python
python爬虫添加请求头代码实例
Dec 28 Python
关于Python 中的时间处理包datetime和arrow的方法详解
Mar 19 Python
python设置表格边框的具体方法
Jul 17 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简单命令代码集锦
2007/09/24 PHP
CodeIgniter针对数据库的连接、配置及使用方法
2016/03/03 PHP
Laravel 5.5基于内置的Auth模块实现前后台登陆详解
2017/12/21 PHP
PHP实现基于3DES算法加密解密字符串示例
2018/08/24 PHP
js利用div背景,做一个竖线的效果。
2008/11/22 Javascript
jquery多浏览器捕捉回车事件代码
2010/06/22 Javascript
JQuery中form验证出错信息的查看方法
2013/10/08 Javascript
js上传图片及预览功能实例分析
2015/04/24 Javascript
avalonjs实现仿微博的图片拖动特效
2015/05/06 Javascript
canvas快速绘制圆形、三角形、矩形、多边形方法介绍
2016/12/29 Javascript
nodejs对express中next函数的一些理解
2017/09/08 NodeJs
JS小球抛物线轨迹运动的两种实现方法详解
2017/12/20 Javascript
浅析Vue 生命周期
2018/06/21 Javascript
Vue项目添加动态浏览器头部title的方法
2018/07/11 Javascript
python解析基于xml格式的日志文件
2017/02/25 Python
Linux 修改Python命令的方法示例
2018/12/03 Python
Python 运行.py文件和交互式运行代码的区别详解
2019/07/02 Python
django 通过url实现简单的权限控制的例子
2019/08/16 Python
flask框架自定义url转换器操作详解
2020/01/25 Python
Python 生成VOC格式的标签实例
2020/03/10 Python
windows10在visual studio2019下配置使用openCV4.3.0
2020/07/14 Python
Auchan Direct波兰:欧尚在线杂货店
2016/10/19 全球购物
有750多个顶级品牌的瑞士时尚在线:ABOUT YOU
2017/01/04 全球购物
Harrods美国:英国最大的百货公司
2018/11/04 全球购物
武汉高蓝德国际.net机试
2016/06/24 面试题
上课睡觉检讨书
2014/01/28 职场文书
运动会通讯稿200字
2014/02/16 职场文书
《乌塔》教学反思
2014/02/17 职场文书
珍爱生命演讲稿
2014/05/10 职场文书
80后婚前协议书范本
2014/10/24 职场文书
考勤制度通知
2015/04/25 职场文书
感恩教育主题班会
2015/08/12 职场文书
小学总务工作总结
2015/08/13 职场文书
小学二年级班主任工作经验交流材料
2015/11/02 职场文书
大学生暑期实践报告之企业经营管理
2019/08/08 职场文书
在Windows Server 2012上安装 .NET Framework 3.5 所遇到的问题
2022/04/29 Servers