基于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如何实现excel数据添加到mongodb
Jul 30 Python
Python+OpenCV人脸检测原理及示例详解
Oct 19 Python
分析Python读取文件时的路径问题
Feb 11 Python
在python中获取div的文本内容并和想定结果进行对比详解
Jan 02 Python
对python中的控制条件、循环和跳出详解
Jun 24 Python
Python3 解决读取中文文件txt编码的问题
Dec 20 Python
Python xpath表达式如何实现数据处理
Jun 13 Python
Python变量格式化输出实现原理解析
Aug 06 Python
记录一下scrapy中settings的一些配置小结
Sep 28 Python
2021年pycharm的最新安装教程及基本使用图文详解
Apr 03 Python
python实现简单聊天功能
Jul 07 Python
python模拟浏览器 使用selenium进入好友QQ空间并留言
Apr 12 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中可能用来加密字符串的函数[base64_encode、urlencode、sha1]
2012/01/16 PHP
php的crc32函数使用时需要注意的问题(不然就是坑)
2015/04/21 PHP
php将金额数字转化为中文大写
2015/07/09 PHP
php根据日期或时间戳获取星座信息和生肖等信息
2015/10/20 PHP
TP5框架实现自定义分页样式的方法示例
2020/04/05 PHP
基于jquery的一个简单的脚本验证插件
2010/04/05 Javascript
JS实现定时页面弹出类似QQ新闻的提示框
2013/11/07 Javascript
jquery map方法使用示例
2014/04/23 Javascript
基于jQuery实现文本框缩放以及上下移动功能
2014/11/24 Javascript
jQuery多条件筛选如何实现
2015/11/04 Javascript
js采用concat和sort将N个数组拼接起来的方法
2016/01/21 Javascript
js 获取本地文件及目录的方法(推荐)
2016/11/10 Javascript
AngularJS之自定义服务详解(factory、service、provider)
2017/04/14 Javascript
angularjs中回车键触发某一事件的方法
2017/04/24 Javascript
在ABP框架中使用BootstrapTable组件的方法
2017/07/31 Javascript
JavaScript基础进阶之数组方法总结(推荐)
2017/09/04 Javascript
使用nodeJs来安装less及编译less文件为css文件的方法
2017/11/20 NodeJs
javascript面向对象程序设计实践常用知识点总结
2019/07/29 Javascript
Python编程中flask的简介与简单使用
2018/12/28 Python
Python字符串和正则表达式中的反斜杠('\')问题详解
2019/09/03 Python
基于FME使用Python过程图解
2020/05/13 Python
python使用bs4爬取boss直聘静态页面
2020/10/10 Python
Django-silk性能测试工具安装及使用解析
2020/11/28 Python
详解matplotlib中pyplot和面向对象两种绘图模式之间的关系
2021/01/22 Python
python re.match()用法相关示例
2021/01/27 Python
CSS3中的注音对齐属性ruby-align用法指南
2016/07/01 HTML / CSS
英国在线发型和美容产品商店:Beauty Cutie
2019/04/27 全球购物
电气个人求职信范文
2014/02/04 职场文书
国际经济与贸易专业大学生职业规划书
2014/03/01 职场文书
单位绩效考核方案
2014/05/11 职场文书
2014法院干警廉洁警示教育思想汇报
2014/09/13 职场文书
施工员岗位职责
2015/02/10 职场文书
创业项目大全(适合在家创业的项目)
2019/08/15 职场文书
Python编写可视化界面的全过程(Python+PyCharm+PyQt)
2021/05/17 Python
浅谈由position属性引申的css进阶讨论
2021/05/25 HTML / CSS
分享一些Java的常用工具
2021/06/11 Java/Android