基于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 相关文章推荐
50行代码实现贪吃蛇(具体思路及代码)
Apr 27 Python
详解Python的Lambda函数与排序
Oct 25 Python
win与linux系统中python requests 安装
Dec 04 Python
Python三级菜单的实例
Sep 13 Python
谈谈python中GUI的选择
Mar 01 Python
使用python读取csv文件快速插入数据库的实例
Jun 21 Python
解决python3运行selenium下HTMLTestRunner报错的问题
Dec 27 Python
Python实现九宫格式的朋友圈功能内附“马云”朋友圈
May 07 Python
django-rest-swagger的优化使用方法
Aug 29 Python
解决Python二维数组赋值问题
Nov 28 Python
Python enumerate内置库用法解析
Feb 24 Python
在python中list作函数形参,防止被实参修改的实现方法
Jun 05 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
非常不错的MySQL优化的8条经验
2008/03/24 PHP
Thinkphp中import的几个用法详细介绍
2014/07/02 PHP
php基于websocket搭建简易聊天室实践
2016/10/24 PHP
thinkPHP3.2.3实现阿里大于短信验证的方法
2018/06/06 PHP
微信公众平台开发教程⑥ 微信开发集成类的使用图文详解
2019/04/10 PHP
jQuery实现跨域
2015/02/03 Javascript
在Python中使用glob模块查找文件路径的方法
2015/06/17 Javascript
bootstrap下拉列表与输入框组结合的样式调整
2016/10/08 Javascript
微信小程序开发之toast等弹框提示使用教程
2017/06/08 Javascript
JS鼠标3次点击事件实现代码及扩展思路
2017/09/12 Javascript
node.js学习之断言assert的使用示例
2017/09/28 Javascript
js判断节假日实例代码
2017/12/27 Javascript
微信小程序button组件使用详解
2018/01/31 Javascript
vue轮播图插件vue-concise-slider的使用
2018/03/13 Javascript
bootstrap中selectpicker下拉框使用方法实例
2018/03/22 Javascript
微信小程序之批量上传并压缩图片的实例代码
2018/07/05 Javascript
js纯前端实现腾讯cos文件上传功能的示例代码
2019/05/14 Javascript
通过实例解析JavaScript for in及for of区别
2020/06/15 Javascript
vue仿携程轮播图效果(滑动轮播,下方高度自适应)
2021/02/11 Vue.js
Python爬虫实战:分析《战狼2》豆瓣影评
2018/03/26 Python
Python实现判断给定列表是否有重复元素的方法
2018/04/11 Python
Python对象与引用的介绍
2019/01/24 Python
python操作日志的封装方法(两种方法)
2019/05/23 Python
如何使用python操作vmware
2019/07/27 Python
Python 70行代码实现简单算式计算器解析
2019/08/30 Python
pandas 中对特征进行硬编码和onehot编码的实现
2019/12/20 Python
Python JSON编解码方式原理详解
2020/01/20 Python
CSS3实现可翻转的hover效果
2018/05/23 HTML / CSS
使用SVG实现提示框功能的示例代码
2020/06/05 HTML / CSS
POP文化和音乐灵感的时尚:Hot Topic
2019/06/19 全球购物
工商治理实习生的自我评价
2014/01/15 职场文书
教师三严三实对照检查材料
2014/09/25 职场文书
销售经理岗位职责
2015/01/31 职场文书
现场施工员岗位职责
2015/04/11 职场文书
不同意离婚代理词
2015/05/23 职场文书
大学生村官驻村工作心得体会
2016/01/23 职场文书