基于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编写一个简单的Lisp解释器的教程
Apr 03 Python
使用C语言扩展Python程序的简单入门指引
Apr 14 Python
Python入门_条件控制(详解)
May 16 Python
Python探索之实现一个简单的HTTP服务器
Oct 28 Python
Java分治归并排序算法实例详解
Dec 12 Python
python中itertools模块zip_longest函数详解
Jun 12 Python
Python合并多个Excel数据的方法
Jul 16 Python
对Python3使运行暂停的方法详解
Feb 18 Python
Python使用paramiko操作linux的方法讲解
Feb 25 Python
Python高级特性与几种函数的讲解
Mar 08 Python
PyQt Qt Designer工具的布局管理详解
Aug 07 Python
Python FFT合成波形的实例
Dec 04 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
星际RPG字典
2020/03/04 星际争霸
用PHP连接Oracle for NT 远程数据库
2006/10/09 PHP
改进的IP计数器
2006/10/09 PHP
php下mysql数据库操作类(改自discuz)
2010/07/03 PHP
探讨Smarty中如何获取数组的长度以及smarty调用php函数的详解
2013/06/20 PHP
php把文件设置为插件的技巧方法
2020/02/03 PHP
jQuery 浮动广告实现代码
2008/12/25 Javascript
js中关于String对象的replace使用详解
2011/05/24 Javascript
25个优雅的jQuery Tooltip插件推荐
2011/05/25 Javascript
通过jQuery源码学习javascript(三)
2012/12/27 Javascript
在jQuery中 关于json空对象筛选替换
2013/04/15 Javascript
jQuery简单几行代码实现tab切换
2015/03/10 Javascript
js下载文件并修改文件名
2017/05/08 Javascript
jQuery访问浏览器本地存储cookie、localStorage和sessionStorage的基本用法
2017/10/20 jQuery
javascript实现QQ空间相册展示源码
2017/12/12 Javascript
浅谈Webpack 是如何加载模块的
2018/05/24 Javascript
Vue.js 中取得后台原生HTML字符串 原样显示问题的解决方法
2018/06/10 Javascript
ES6 对象的新功能与解构赋值介绍
2019/02/05 Javascript
利用webpack理解CommonJS和ES Modules的差异区别
2020/06/16 Javascript
vue相同路由跳转强制刷新该路由组件操作
2020/08/05 Javascript
[05:06]2017亚洲邀请赛DAC回顾片
2017/04/19 DOTA
MxNet预训练模型到Pytorch模型的转换方式
2020/05/25 Python
如何用Python绘制3D柱形图
2020/09/16 Python
美国价格实惠的在线眼镜网站:Zeelool
2020/12/25 全球购物
教育科学研究生自荐信
2013/10/09 职场文书
父亲八十大寿答谢词
2014/01/23 职场文书
畜牧兽医本科生的自我评价
2014/03/03 职场文书
老师对学生的寄语
2014/04/09 职场文书
大学新学期计划书
2014/04/28 职场文书
摄影展策划方案
2014/06/02 职场文书
水利水电建筑施工应届生求职信
2014/07/04 职场文书
2015届本科毕业生自我鉴定
2014/09/27 职场文书
护理专业自荐信范文
2015/03/06 职场文书
幽灵公主观后感
2015/06/09 职场文书
2016年感恩父亲节活动总结
2016/04/01 职场文书
企业开发CSS命名BEM代码规范实践
2022/02/12 HTML / CSS