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列出目录下指定文件与子目录的方法
Jul 03 Python
浅析python中的分片与截断序列
Aug 09 Python
python中利用await关键字如何等待Future对象完成详解
Sep 07 Python
Django基于ORM操作数据库的方法详解
Mar 27 Python
python random从集合中随机选择元素的方法
Jan 23 Python
python实现石头剪刀布程序
Jan 20 Python
matplotlib实现区域颜色填充
Mar 18 Python
快速解决pyqt5窗体关闭后子线程不同时退出的问题
Jun 19 Python
pytorch实现mnist数据集的图像可视化及保存
Jan 14 Python
PYcharm 激活方法(推荐)
Mar 23 Python
基于python实现把json数据转换成Excel表格
May 07 Python
Prometheus开发中间件Exporter过程详解
Nov 30 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+MYSQL的文章管理系统(二)
2006/10/09 PHP
UCenter 批量添加用户的php代码
2012/07/17 PHP
PHP strstr 函数判断字符串是否否存在的实例代码
2013/09/28 PHP
php通过正则表达式记取数据来读取xml的方法
2015/03/09 PHP
PHP内核探索之变量
2015/12/22 PHP
PHP MYSQL简易交互式站点开发
2016/12/27 PHP
javascript 表单规则集合对象
2009/07/21 Javascript
JS 显示当前日期与时间的代码
2010/03/24 Javascript
js最简单的拖拽效果实现代码
2010/09/24 Javascript
当鼠标移动到图片上时跟随鼠标显示放大的图片效果
2013/06/06 Javascript
JS图片根据鼠标滚动延时加载的实例代码
2013/07/13 Javascript
在页面中js获取光标/鼠标的坐标及光标的像素坐标
2013/11/11 Javascript
bootstrap table使用入门基本用法
2017/05/24 Javascript
AngularJS实现单一页面内设置跳转路由的方法
2017/06/28 Javascript
JSON创建键值对(key是中文或者数字)方式详解
2017/08/24 Javascript
Vue中添加手机验证码组件功能操作方法
2017/12/07 Javascript
JS中获取 DOM 元素的绝对位置实例详解
2018/04/23 Javascript
Element Input组件分析小结
2018/10/11 Javascript
浅入深出Vue之自动化路由
2019/08/06 Javascript
Emberjs 通过 axios 下载文件的方法
2019/09/03 Javascript
前端深入理解Typescript泛型概念
2020/03/09 Javascript
Js图片点击切换轮播实现代码
2020/07/27 Javascript
python通过openpyxl生成Excel文件的方法
2015/05/12 Python
使用Python神器对付12306变态验证码
2016/01/05 Python
Python 实现两个列表里元素对应相乘的方法
2018/11/14 Python
Python实现正则表达式匹配任意的邮箱方法
2018/12/20 Python
python爬虫中多线程的使用详解
2019/09/23 Python
wxpython+pymysql实现用户登陆功能
2019/11/19 Python
详解css3 flex弹性盒自动铺满写法
2020/09/17 HTML / CSS
南非领先的在线旅行社:Travelstart南非
2016/09/04 全球购物
伊芙丽官方旗舰店:中国淑女一线品牌
2017/12/01 全球购物
2014年护士个人工作总结
2014/11/11 职场文书
2014年终工作总结范本
2014/12/15 职场文书
总账会计岗位职责
2015/04/02 职场文书
初中运动会闭幕词范本3篇
2019/12/09 职场文书
mysql拆分字符串作为查询条件的示例代码
2022/07/07 MySQL