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 相关文章推荐
有关wxpython pyqt内存占用问题分析
Jun 09 Python
Python中List.count()方法的使用教程
May 20 Python
Python实现简单拆分PDF文件的方法
Jul 30 Python
利用Anaconda完美解决Python 2与python 3的共存问题
May 25 Python
基于python进行桶排序与基数排序的总结
May 29 Python
python实现Windows电脑定时关机
Jun 20 Python
在numpy矩阵中令小于0的元素改为0的实例
Jan 26 Python
Django后端接收嵌套Json数据及解析详解
Jul 17 Python
Django 开发调试工具 Django-debug-toolbar使用详解
Jul 23 Python
Python退出时强制运行一段代码的实现方法
Apr 29 Python
keras打印loss对权重的导数方式
Jun 10 Python
python怎么删除缓存文件
Jul 19 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下关于中英数字混排的字符串分割问题
2010/04/06 PHP
shell脚本作为保证PHP脚本不挂掉的守护进程实例分享
2013/07/15 PHP
在PHP上显示JFreechart画的统计图方法
2013/11/03 PHP
thinkphp实现163、QQ邮箱收发邮件的方法
2015/12/18 PHP
PHP连接MYSQL数据库实例代码
2016/01/20 PHP
PHP简单判断手机设备的方法
2016/08/23 PHP
PHP导出带样式的Excel示例代码
2016/08/28 PHP
实例讲解PHP中使用命名空间
2019/01/27 PHP
IE浏览器PNG图片透明效果代码
2008/09/02 Javascript
js 代码集(学习js的朋友可以看下)
2009/07/22 Javascript
javascript克隆对象深度介绍
2012/11/20 Javascript
Javascript写入txt和读取txt文件示例
2014/02/12 Javascript
node.js下when.js 的异步编程实践
2014/12/03 Javascript
AngularJS监听路由变化的方法
2017/03/07 Javascript
vue axios整合使用全攻略
2018/05/24 Javascript
详解基于Node.js的HTTP/2 Server实践
2018/05/31 Javascript
在 vue-cli v3.0 中使用 SCSS/SASS的方法
2018/06/14 Javascript
angularjs中判断ng-repeat是否迭代完的实例
2018/09/12 Javascript
JavaScript实现的拼图算法分析
2019/02/13 Javascript
Python全局变量用法实例分析
2016/07/19 Python
Python数据拟合与广义线性回归算法学习
2017/12/22 Python
python实现彩色图转换成灰度图
2019/01/15 Python
cProfile Python性能分析工具使用详解
2019/07/22 Python
解决Tensorflow 内存泄露问题
2020/02/05 Python
浅谈pytorch 模型 .pt, .pth, .pkl的区别及模型保存方式
2020/05/25 Python
Python字典实现伪切片功能
2020/10/28 Python
Python 使用xlwt模块将多行多列数据循环写入excel文档的操作
2020/11/10 Python
Lookfantastic西班牙官网:英国知名美妆购物网站
2018/06/13 全球购物
全球性的在线鞋类品牌:Public Desire
2019/04/03 全球购物
韩国乐天网上商城:Lotte iMall
2021/02/03 全球购物
写给女朋友的道歉信
2014/01/12 职场文书
中专生自我鉴定范文
2014/02/02 职场文书
车间安全生产标语
2014/06/06 职场文书
2015年控辍保学工作总结
2015/05/18 职场文书
Python实现天气查询软件
2021/06/07 Python
MySQL 数据表操作
2022/05/04 MySQL