基于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 12 Python
Python MySQLdb模块连接操作mysql数据库实例
Apr 08 Python
Python每天必学之bytes字节
Jan 28 Python
Python实现两款计算器功能示例
Dec 19 Python
python删除过期log文件操作实例解析
Jan 31 Python
Python利用递归实现文件的复制方法
Oct 27 Python
python中hasattr()、getattr()、setattr()函数的使用
Aug 16 Python
python中@property和property函数常见使用方法示例
Oct 21 Python
Pytorch 多维数组运算过程的索引处理方式
Dec 27 Python
django模板获取list中指定索引的值方式
May 14 Python
python下载的库包存放路径
Jul 27 Python
Python 中 Shutil 模块详情
Nov 11 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版 汉字转码的实现详解
2013/06/09 PHP
mac下安装nginx和php
2013/11/04 PHP
php $_SERVER windows系统与linux系统下的区别说明
2014/02/14 PHP
thinkphp特殊标签用法概述
2014/11/24 PHP
php提交表单发送邮件的方法
2015/03/20 PHP
实现WordPress主题侧边栏切换功能的PHP脚本详解
2015/12/14 PHP
php-msf源码详解
2017/12/25 PHP
比较全的JS checkbox全选、取消全选、删除功能代码
2008/12/19 Javascript
JS实现仿百度输入框自动匹配功能的示例代码
2014/02/19 Javascript
javascript实现锁定网页、密码解锁效果(类似系统屏幕保护效果)
2014/08/15 Javascript
jQuery中[attribute=value]选择器用法实例
2014/12/31 Javascript
jQuery调用ajax请求的常见方法汇总
2015/03/24 Javascript
jQuery实现仿QQ在线客服效果的滚动层代码
2015/10/15 Javascript
Jquery插件之Fancybox丰富的弹出层效果附源码下载
2015/12/02 Javascript
java必学必会之static关键字
2015/12/03 Javascript
jQuery获取浏览器类型和版本号的方法
2016/07/05 Javascript
JS获取及验证开始结束日期的方法
2016/08/20 Javascript
获取jqGrid中选择的行的数据
2016/11/30 Javascript
如何给ss bash 写一个 WEB 端查看流量的页面
2017/03/23 Javascript
react.js CMS 删除功能的实现方法
2017/04/17 Javascript
浅谈angular.js跨域post解决方案
2017/08/30 Javascript
Vue.js 中取得后台原生HTML字符串 原样显示问题的解决方法
2018/06/10 Javascript
JS实现数组去重,显示重复元素及个数的方法示例
2019/01/21 Javascript
详解package.json版本号规则
2019/08/01 Javascript
js实现点击上传图片并设为模糊背景
2020/08/02 Javascript
Python操作SQLite数据库的方法详解
2017/06/16 Python
pycharm远程调试openstack的图文教程
2017/11/21 Python
python广度优先搜索得到两点间最短路径
2019/01/17 Python
python网络编程 使用UDP、TCP协议收发信息详解
2019/08/29 Python
python中def是做什么的
2020/06/10 Python
python中通过pip安装库文件时出现“EnvironmentError: [WinError 5] 拒绝访问”的问题及解决方案
2020/08/11 Python
Python getsizeof()和getsize()区分详解
2020/11/20 Python
利用简洁的图片预加载组件提升html5移动页面的用户体验
2016/03/11 HTML / CSS
html5的pushstate以及监听浏览器返回事件的实现
2020/08/11 HTML / CSS
日本最大的购物网站乐天市场国际版:Rakuten Global Market(支持中文)
2020/02/03 全球购物
个人三严三实对照检查材料
2014/09/25 职场文书