Python定义一个Actor任务


Posted in Python onJuly 29, 2020

问题

你想定义跟actor模式中类似“actors”角色的任务

解决方案

actor模式是一种最古老的也是最简单的并行和分布式计算解决方案。 事实上,它天生的简单性是它如此受欢迎的重要原因之一。 简单来讲,一个actor就是一个并发执行的任务,只是简单的执行发送给它的消息任务。 响应这些消息时,它可能还会给其他actor发送更进一步的消息。 actor之间的通信是单向和异步的。因此,消息发送者不知道消息是什么时候被发送, 也不会接收到一个消息已被处理的回应或通知。

结合使用一个线程和一个队列可以很容易的定义actor,例如:

from queue import Queue
from threading import Thread, Event

# Sentinel used for shutdown
class ActorExit(Exception):
  pass

class Actor:
  def __init__(self):
    self._mailbox = Queue()

  def send(self, msg):
    '''
    Send a message to the actor
    '''
    self._mailbox.put(msg)

  def recv(self):
    '''
    Receive an incoming message
    '''
    msg = self._mailbox.get()
    if msg is ActorExit:
      raise ActorExit()
    return msg

  def close(self):
    '''
    Close the actor, thus shutting it down
    '''
    self.send(ActorExit)

  def start(self):
    '''
    Start concurrent execution
    '''
    self._terminated = Event()
    t = Thread(target=self._bootstrap)

    t.daemon = True
    t.start()

  def _bootstrap(self):
    try:
      self.run()
    except ActorExit:
      pass
    finally:
      self._terminated.set()

  def join(self):
    self._terminated.wait()

  def run(self):
    '''
    Run method to be implemented by the user
    '''
    while True:
      msg = self.recv()

# Sample ActorTask
class PrintActor(Actor):
  def run(self):
    while True:
      msg = self.recv()
      print('Got:', msg)

# Sample use
p = PrintActor()
p.start()
p.send('Hello')
p.send('World')
p.close()
p.join()

这个例子中,你使用actor实例的 send() 方法发送消息给它们。 其机制是,这个方法会将消息放入一个队里中, 然后将其转交给处理被接受消息的一个内部线程。 close() 方法通过在队列中放入一个特殊的哨兵值(ActorExit)来关闭这个actor。 用户可以通过继承Actor并定义实现自己处理逻辑run()方法来定义新的actor。 ActorExit 异常的使用就是用户自定义代码可以在需要的时候来捕获终止请求 (异常被get()方法抛出并传播出去)。

如果你放宽对于同步和异步消息发送的要求, 类actor对象还可以通过生成器来简化定义。例如:

def print_actor():
  while True:

    try:
      msg = yield   # Get a message
      print('Got:', msg)
    except GeneratorExit:
      print('Actor terminating')

# Sample use
p = print_actor()
next(p)   # Advance to the yield (ready to receive)
p.send('Hello')
p.send('World')
p.close()

讨论

actor模式的魅力就在于它的简单性。 实际上,这里仅仅只有一个核心操作 send() . 甚至,对于在基于actor系统中的“消息”的泛化概念可以已多种方式被扩展。 例如,你可以以元组形式传递标签消息,让actor执行不同的操作,如下:

class TaggedActor(Actor):
  def run(self):
    while True:
       tag, *payload = self.recv()
       getattr(self,'do_'+tag)(*payload)

  # Methods correponding to different message tags
  def do_A(self, x):
    print('Running A', x)

  def do_B(self, x, y):
    print('Running B', x, y)

# Example
a = TaggedActor()
a.start()
a.send(('A', 1))   # Invokes do_A(1)
a.send(('B', 2, 3))  # Invokes do_B(2,3)
a.close()
a.join()

作为另外一个例子,下面的actor允许在一个工作者中运行任意的函数, 并且通过一个特殊的Result对象返回结果:

from threading import Event
class Result:
  def __init__(self):
    self._evt = Event()
    self._result = None

  def set_result(self, value):
    self._result = value

    self._evt.set()

  def result(self):
    self._evt.wait()
    return self._result

class Worker(Actor):
  def submit(self, func, *args, **kwargs):
    r = Result()
    self.send((func, args, kwargs, r))
    return r

  def run(self):
    while True:
      func, args, kwargs, r = self.recv()
      r.set_result(func(*args, **kwargs))

# Example use
worker = Worker()
worker.start()
r = worker.submit(pow, 2, 3)
worker.close()
worker.join()
print(r.result())

最后,“发送”一个任务消息的概念可以被扩展到多进程甚至是大型分布式系统中去。 例如,一个类actor对象的 send() 方法可以被编程让它能在一个套接字连接上传输数据 或通过某些消息中间件(比如AMQP、ZMQ等)来发送。

以上就是Python定义一个Actor任务的详细内容,更多关于Python actor任务的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python通过pil模块将raw图片转换成png图片的方法
Mar 16 Python
修改Python的pyxmpp2中的主循环使其提高性能
Apr 24 Python
Python获取系统默认字符编码的方法
Jun 04 Python
Python进阶-函数默认参数(详解)
May 18 Python
python 3.6 +pyMysql 操作mysql数据库(实例讲解)
Dec 20 Python
Python基于whois模块简单识别网站域名及所有者的方法
Apr 23 Python
python实现生成字符串大小写字母和数字的各种组合
Jan 01 Python
python全栈要学什么 python全栈学习路线
Jun 28 Python
Python 开发工具PyCharm安装教程图文详解(新手必看)
Feb 28 Python
Python命名空间及作用域原理实例解析
Aug 12 Python
通过代码实例了解Python3编程技巧
Oct 13 Python
python 简单的调用有道翻译
Nov 25 Python
Python如何重新加载模块
Jul 29 #Python
Python加速程序运行的方法
Jul 29 #Python
如何在python中判断变量的类型
Jul 29 #Python
Python中的With语句的使用及原理
Jul 29 #Python
解决c++调用python中文乱码问题
Jul 29 #Python
Python 实现简单的客户端认证
Jul 29 #Python
Tensorflow使用Anaconda、pycharm安装记录
Jul 29 #Python
You might like
PHP的宝库目录--PEAR
2006/10/09 PHP
五款常用mysql slow log分析工具的比较分析
2011/05/22 PHP
php中时间轴开发(刚刚、5分钟前、昨天10:23等)
2011/10/03 PHP
PHP 9 大缓存技术总结
2015/09/17 PHP
浅谈laravel框架sql中groupBy之后排序的问题
2019/10/17 PHP
在线编辑器中换行与内容自动提取
2009/04/24 Javascript
JS维吉尼亚密码算法实现代码
2010/11/09 Javascript
jQuery学习笔记之jQuery的动画
2010/12/22 Javascript
JavaScript中的this实例分析
2011/04/28 Javascript
图标线性回归斜着移动到指定的位置
2013/08/16 Javascript
jQuery修改class属性和CSS样式整理
2015/01/30 Javascript
如何用javascript计算文本框还能输入多少个字符
2015/07/29 Javascript
javascript实现计时器的简单方法
2016/02/21 Javascript
Select2.js下拉框使用小结
2016/10/24 Javascript
js 作用域和变量详解
2017/02/16 Javascript
利用js查找数组中指定元素并返回该元素的所有索引示例
2017/03/29 Javascript
vue 2.0路由之路由嵌套示例详解
2017/05/08 Javascript
JS实现新建文件夹功能
2017/06/17 Javascript
在Vue-cli里应用Vuex的state和mutations方法
2018/09/16 Javascript
详解如何在vue项目中使用eslint+prettier格式化代码
2018/11/10 Javascript
PHPStorm中如何对nodejs项目进行单元测试详解
2019/02/28 NodeJs
微信小程序实现点击卡片 翻转效果
2019/09/04 Javascript
python队列通信:rabbitMQ的使用(实例讲解)
2017/12/22 Python
Django如何实现上传图片功能
2019/08/16 Python
python生成13位或16位时间戳以及反向解析时间戳的实例
2020/03/03 Python
使用TensorBoard进行超参数优化的实现
2020/07/06 Python
详解CSS3 filter:drop-shadow滤镜与box-shadow区别与应用
2020/08/24 HTML / CSS
香港草莓网土耳其网站:Strawberrynet TR
2017/03/02 全球购物
计算机专业个人求职信范例
2013/09/23 职场文书
英语专业个人求职信范文
2014/02/01 职场文书
乡镇防汛工作汇报
2014/10/28 职场文书
个人学习群众路线心得体会
2014/11/05 职场文书
2015年会计个人工作总结
2015/04/02 职场文书
师德师风心得体会(2016精选篇)
2016/01/12 职场文书
如何用JS实现网页瀑布流布局
2021/04/24 Javascript
使用Python拟合函数曲线
2022/04/14 Python