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 相关文章推荐
Python3中常用的处理时间和实现定时任务的方法的介绍
Apr 07 Python
解密Python中的描述符(descriptor)
Jun 03 Python
使用Python导出Excel图表以及导出为图片的方法
Nov 07 Python
python使用opencv进行人脸识别
Apr 07 Python
Python简单实现Base64编码和解码的方法
Apr 29 Python
python:pandas合并csv文件的方法(图书数据集成)
Apr 12 Python
基于anaconda下强大的conda命令介绍
Jun 11 Python
windows下pycharm安装、创建文件、配置默认模板
Jul 31 Python
python求解数组中两个字符串的最小距离
Sep 27 Python
Python符号计算之实现函数极限的方法
Jul 15 Python
用Python实现童年贪吃蛇小游戏功能的实例代码
Dec 07 Python
python之PySide2安装使用及QT Designer UI设计案例教程
Jul 26 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/03/27 PHP
PHP通过内置函数memory_get_usage()获取内存使用情况
2014/11/20 PHP
PHP浮点数的一个常见问题
2016/03/10 PHP
php实现构建排除当前元素的乘积数组方法
2018/10/06 PHP
PHP PDOStatement::getAttribute讲解
2019/02/01 PHP
初学js 新节点的创建 删除 的步骤
2011/07/04 Javascript
输入框的字数时时统计—关于 onpropertychange 和 oninput 使用
2011/10/21 Javascript
6款新颖的jQuery和CSS3进度条插件推荐
2013/03/05 Javascript
Extjs4 GridPanel的主要配置参数详细介绍
2013/04/18 Javascript
基于jquery实现的省市区级联无ajax
2013/09/24 Javascript
JS画线(实例代码)
2013/11/20 Javascript
jQuery中 prop() attr()使用详解
2015/05/19 Javascript
Jquery解析json字符串及json数组的方法
2015/05/29 Javascript
解决JS请求服务器gbk文件乱码的问题
2015/10/16 Javascript
Bootstrap组件系列之福利篇几款好用的组件(推荐二)
2016/07/12 Javascript
JavaScript中闭包之浅析解读(必看篇)
2016/08/25 Javascript
Angular2 (RC4) 路由与导航详解
2016/09/21 Javascript
JS和canvas实现俄罗斯方块
2017/03/14 Javascript
JS异步加载的三种实现方式
2017/03/16 Javascript
JS查找数组中重复元素的方法详解
2017/06/14 Javascript
基于AngularJS的拖拽文件上传的实例代码
2017/07/15 Javascript
JS开发中基本数据类型具体有哪几种
2017/10/19 Javascript
微信小程序日历插件代码实例
2019/12/04 Javascript
python创建只读属性对象的方法(ReadOnlyObject)
2013/02/10 Python
使用 Python 获取 Linux 系统信息的代码
2014/07/13 Python
Python列表推导式与生成器表达式用法示例
2018/02/08 Python
python MysqlDb模块安装及其使用详解
2018/02/23 Python
python自动发邮件总结及实例说明【推荐】
2019/05/31 Python
python中下标和切片的使用方法解析
2019/08/27 Python
使用matlab或python将txt文件转为excel表格
2019/11/01 Python
基于python实现从尾到头打印链表
2019/11/02 Python
Python 执行矩阵与线性代数运算
2020/08/01 Python
艺术系大学生毕业个人自我评价
2013/09/19 职场文书
卫校毕业生自我鉴定
2014/09/28 职场文书
大学生军训心得体会5篇
2019/08/15 职场文书
关于Spring配置文件加载方式变化引发的异常详解
2022/01/18 Java/Android