基于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代码使其加快作用域内的查找
Mar 30 Python
Python多线程和队列操作实例
Jun 21 Python
Python数据分析之双色球中蓝红球分析统计示例
Feb 03 Python
python 把文件中的每一行以数组的元素放入数组中的方法
Apr 29 Python
python查看列的唯一值方法
Jul 17 Python
基于python实现学生管理系统
Oct 17 Python
使用memory_profiler监测python代码运行时内存消耗方法
Dec 03 Python
vscode 配置 python3开发环境的方法
Sep 19 Python
python统计字符串中字母出现次数代码实例
Mar 02 Python
python脚本定时发送邮件
Dec 22 Python
详解Open Folder as PyCharm Project怎么添加的方法
Dec 29 Python
python中redis包操作数据库的教程
Apr 19 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设计模式 Delegation(委托模式)
2011/06/26 PHP
php实现根据url自动生成缩略图的方法
2014/09/23 PHP
PHP SPL标准库之接口(Interface)详解
2015/05/11 PHP
PHP脚本监控Nginx 502错误并自动重启php-fpm
2015/05/13 PHP
Zend Framework框架路由机制代码分析
2016/03/22 PHP
[原创]PHP实现字节数Byte转换为KB、MB、GB、TB的方法
2017/08/31 PHP
30个最佳jQuery Lightbox效果插件分享
2011/04/11 Javascript
各种页面定时跳转(倒计时跳转)代码总结
2013/10/24 Javascript
node.js中的fs.rename方法使用说明
2014/12/16 Javascript
理解javascript中的with关键字
2016/02/15 Javascript
JavaScript学习笔记之数组求和方法
2016/03/23 Javascript
jquery mobile界面数据刷新的实现方法
2016/05/28 Javascript
Javascript基础_嵌入图像的简单实现
2016/06/14 Javascript
清除浏览器缓存的几种方法总结(必看)
2016/12/09 Javascript
js 将input框中的输入自动转化成半角大写(税号输入框)
2017/02/16 Javascript
jQuery Plupload上传插件的使用
2017/04/19 jQuery
js上传图片预览的实现方法
2017/05/09 Javascript
bootstrap+jQuery 实现下拉菜单中复选框全选和全不选效果
2017/06/12 jQuery
jQuery上传插件webupload使用方法
2017/08/01 jQuery
node.js中process进程的概念和child_process子进程模块的使用方法示例
2020/02/11 Javascript
vue data变量相互赋值后被实时同步的解决步骤
2020/08/05 Javascript
使用Python脚本对Linux服务器进行监控的教程
2015/04/02 Python
Pycharm之快速定位到某行快捷键的方法
2019/01/20 Python
Python 网络编程之TCP客户端/服务端功能示例【基于socket套接字】
2019/10/12 Python
浅谈python处理json和redis hash的坑
2020/07/16 Python
CSS3 2D模拟实现摩天轮旋转效果
2016/11/16 HTML / CSS
《翻越远方的大山》教学反思
2014/04/13 职场文书
食品质量与安全专业毕业生求职信
2014/08/11 职场文书
群众路线查摆问题整改措施
2014/10/10 职场文书
买房子个人收入证明
2014/10/12 职场文书
项目转让协议书
2014/10/27 职场文书
租车协议书范本2014
2014/11/17 职场文书
教师理论学习心得体会
2016/01/21 职场文书
高并发下Redis如何保持数据一致性(避免读后写)
2022/03/18 Redis
nginx刷新页面出现404解决方案(亲测有效)
2022/03/18 Servers
MySQL限制查询和数据排序介绍
2022/03/25 MySQL