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中requests模块的使用方法
Apr 08 Python
用Python操作字符串之rindex()方法的使用
May 19 Python
python制作爬虫并将抓取结果保存到excel中
Apr 06 Python
git使用.gitignore设置不生效或不起作用问题的解决方法
Jun 01 Python
Python实现的根据文件名查找数据文件功能示例
May 02 Python
python基于http下载视频或音频
Jun 20 Python
Python实现去除图片中指定颜色的像素功能示例
Apr 13 Python
Django ORM 自定义 char 类型字段解析
Aug 09 Python
使用python去除图片白色像素的实例
Dec 12 Python
python中的subprocess.Popen()使用详解
Dec 25 Python
Python抓包并解析json爬虫的完整实例代码
Nov 03 Python
python 办公自动化——基于pyqt5和openpyxl统计符合要求的名单
May 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设计模式中的工厂模式
2008/06/12 PHP
Linux下实现PHP多进程的方法分享
2012/08/16 PHP
ThinkPHP中I(),U(),$this->post()等函数用法
2014/11/22 PHP
php中array_unshift()修改数组key注意事项分析
2016/05/16 PHP
JavaScript高级程序设计 客户端存储学习笔记
2011/09/10 Javascript
Javascript面向对象扩展库代码分享
2012/03/27 Javascript
jquery ajax例子返回值详解
2012/09/11 Javascript
jQuery滚动加载图片效果的实现
2013/03/06 Javascript
javascript计时器事件使用详解
2014/01/07 Javascript
用jQuery toggleClass 实现鼠标移上变色
2014/05/14 Javascript
jquery和css3实现的炫酷时尚的菜单导航
2014/09/01 Javascript
jquery实现类似淘宝星星评分功能实例
2014/09/12 Javascript
JavaScript中的包装对象介绍
2015/01/27 Javascript
js封装tab标签页实例分享
2016/12/19 Javascript
DropDownList控件绑定数据源的三种方法
2016/12/24 Javascript
AngularJS表单基本操作
2017/01/09 Javascript
jQuery点击弹出层弹出模态框点击模态框消失代码分享
2017/01/21 Javascript
巧用canvas
2017/01/21 Javascript
JavaScript关联数组用法分析【概念、定义、遍历】
2017/03/15 Javascript
一个Js文件函数中调用另一个Js文件函数的方法演示
2017/08/14 Javascript
详解tween.js 中文使用指南
2018/01/05 Javascript
JS中的算法与数据结构之队列(Queue)实例详解
2019/08/20 Javascript
Python 命令行非阻塞输入的小例子
2013/09/27 Python
Python六大开源框架对比
2015/10/19 Python
pandas通过索引进行排序的示例
2018/11/16 Python
HTML5拖放API实现拖放排序的实例代码
2017/05/11 HTML / CSS
财政局长自荐信范文
2013/12/22 职场文书
邮政员工辞职信
2014/01/16 职场文书
《只有一个地球》教学反思
2014/02/14 职场文书
低碳生活倡议书
2014/04/14 职场文书
药剂专业个人求职信范文
2014/04/29 职场文书
保险专业求职信
2014/07/07 职场文书
孔庙导游词
2015/02/04 职场文书
学习经验交流会总结
2015/11/02 职场文书
python中的None与NULL用法说明
2021/05/25 Python
javascript条件式访问属性和箭头函数介绍
2021/11/17 Javascript