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 07 Python
跟老齐学Python之关于循环的小伎俩
Oct 02 Python
用Python给文本创立向量空间模型的教程
Apr 23 Python
详解Python使用simplejson模块解析JSON的方法
Mar 24 Python
浅谈numpy数组的几种排序方式
Dec 15 Python
Python解析命令行读取参数之argparse模块
Jul 26 Python
python3 dict ndarray 存成json,并保留原数据精度的实例
Dec 06 Python
Pytorch释放显存占用方式
Jan 13 Python
浅谈pytorch torch.backends.cudnn设置作用
Feb 20 Python
pytorch:model.train和model.eval用法及区别详解
Feb 20 Python
浅谈python 中的 type(), dtype(), astype()的区别
Apr 09 Python
python如何读取.mtx文件
Apr 22 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
smarty简单分页的实现方法
2014/10/27 PHP
thinkPHP分页功能实例详解
2017/05/05 PHP
自动完成JS类(纯JS, Ajax模式)
2009/03/12 Javascript
jQuery 常见开发使用技巧总结
2009/12/26 Javascript
Jquery替换已存在于element上的event的方法
2010/03/09 Javascript
php 中序列化和json使用介绍
2013/07/08 Javascript
jQuery实现鼠标滑过Div层背景变颜色的方法
2015/02/17 Javascript
jQuery实现切换页面过渡动画效果
2015/10/29 Javascript
自己动手写的javascript前端等待控件
2015/10/30 Javascript
jQuery表格插件datatables用法详解
2020/11/23 Javascript
JQuery日历插件My97DatePicker日期范围限制
2016/01/20 Javascript
快速掌握Node.js之Window下配置NodeJs环境
2016/03/21 NodeJs
JavaScript之事件委托实例(附原生js和jQuery代码)
2017/07/22 jQuery
JS中promise化微信小程序api
2018/04/12 Javascript
小程序如何写动态标签的实现方法
2020/02/05 Javascript
在vue中封装方法以及多处引用该方法详解
2020/08/14 Javascript
基于js实现的图片拖拽排序源码实例
2020/11/04 Javascript
原生JS实现音乐播放器
2021/01/26 Javascript
简述Python中的面向对象编程的概念
2015/04/27 Python
举例讲解Python设计模式编程中的访问者与观察者模式
2016/01/26 Python
Python实现的计算器功能示例
2018/04/26 Python
对Python中9种生成新对象的方法总结
2018/05/23 Python
如何不用安装python就能在.NET里调用Python库
2019/07/12 Python
python编写俄罗斯方块
2020/03/13 Python
简单了解django处理跨域请求最佳解决方案
2020/03/25 Python
莱德杯高尔夫欧洲官方商店:Ryder Cup Shop
2019/08/14 全球购物
关于毕业的广播稿
2014/01/10 职场文书
腾讯广告词
2014/03/19 职场文书
文明寝室申报材料
2014/05/12 职场文书
自查自纠工作总结
2014/10/15 职场文书
2014年乡镇人大工作总结
2014/11/25 职场文书
新生入学欢迎词
2015/01/26 职场文书
寒山寺导游词
2015/02/03 职场文书
2015年街道除四害工作总结
2015/05/15 职场文书
导游词之千岛湖
2019/09/23 职场文书
导游词之上海东方明珠塔
2019/09/25 职场文书