基于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 相关文章推荐
Python3基础之输入和输出实例分析
Aug 18 Python
python中日期和时间格式化输出的方法小结
Mar 19 Python
Python的函数的一些高阶特性
Apr 27 Python
插入排序_Python与PHP的实现版(推荐)
May 11 Python
python 自动去除空行的实例
Jul 24 Python
Django stark组件使用及原理详解
Aug 22 Python
pytorch 实现在一个优化器中设置多个网络参数的例子
Feb 20 Python
Python GUI编程学习笔记之tkinter事件绑定操作详解
Mar 30 Python
matplotlib 对坐标的控制,加图例注释的操作
Apr 17 Python
pycharm 实现光标快速移动到括号外或行尾的操作
Feb 05 Python
python编写函数注意事项总结
Mar 29 Python
Django中celery的使用项目实例
Jul 07 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
Joomla实现组件中弹出一个模式(modal)窗口的方法
2016/05/04 PHP
红米手机抢购的js代码
2014/03/10 Javascript
jQuery使用serialize()表单序列化时出现中文乱码问题的解决办法
2016/07/27 Javascript
js实现目录链接,内容跟着目录滚动显示的简单实例
2016/10/15 Javascript
Bootstrap栅格系统的使用和理解2
2016/12/14 Javascript
详解jQuery中的事件
2016/12/14 Javascript
ThinkPHP+jquery实现“加载更多”功能代码
2017/03/11 Javascript
详解vue.js的事件处理器v-on:click
2017/06/27 Javascript
以BootStrap Tab为例写一个前端组件
2017/07/25 Javascript
详解在vue-cli项目中使用mockjs(请求数据删除数据)
2017/10/23 Javascript
js中getBoundingClientRect的作用及兼容方案详解
2018/02/01 Javascript
JavaScript常见事件处理程序实例总结
2019/01/05 Javascript
微信小程序上传多图到服务器并获取返回的路径
2019/05/05 Javascript
JS使用正则表达式判断输入框失去焦点事件
2019/10/16 Javascript
vue路由传参三种基本方式详解
2019/12/09 Javascript
vue下axios拦截器token刷新机制的实例代码
2020/01/17 Javascript
解决Vue 给mapState中定义的属性赋值报错的问题
2020/06/22 Javascript
vue实现简易计算器功能
2021/01/20 Vue.js
跟老齐学Python之编写类之四再论继承
2014/10/11 Python
Ubuntu安装Jupyter Notebook教程
2017/10/18 Python
python线程池threadpool使用篇
2018/04/27 Python
对Pycharm创建py文件时自定义头部模板的方法详解
2019/02/12 Python
python基于plotly实现画饼状图代码实例
2019/12/16 Python
python分布式计算dispy的使用详解
2019/12/22 Python
keras小技巧——获取某一个网络层的输出方式
2020/05/23 Python
使用PyWeChatSpy自动回复微信拍一拍功能的实现代码
2020/07/02 Python
python 获取谷歌浏览器保存的密码
2021/01/06 Python
浅谈amaze-ui中datepicker和datetimepicker注意的几点
2020/08/21 HTML / CSS
英国最大的笔记本电脑直销专家:Laptops Direct
2019/07/20 全球购物
力学专业毕业生自荐信
2013/11/17 职场文书
平面设计求职信
2014/03/10 职场文书
2014年政工师工作总结
2014/12/18 职场文书
自荐信范文
2019/05/20 职场文书
SQLServer2008提示评估期已过解决方案
2021/04/12 SQL Server
浅谈MySQL之select优化方案
2021/08/07 MySQL
开发微信小程序之WXSS样式教程
2022/04/18 HTML / CSS