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编写C/S网络程序实例教程
Aug 25 Python
用Python制作简单的朴素基数估计器的教程
Apr 01 Python
用C++封装MySQL的API的教程
May 06 Python
python获取代码运行时间的实例代码
Jun 11 Python
pandas.DataFrame删除/选取含有特定数值的行或列实例
Nov 07 Python
Python+OpenCV感兴趣区域ROI提取方法
Jan 10 Python
PyTorch之图像和Tensor填充的实例
Aug 18 Python
Python实现图像去噪方式(中值去噪和均值去噪)
Dec 18 Python
Python实现汇率转换操作
May 03 Python
Pycharm无法打开双击没反应的问题及解决方案
Aug 17 Python
python regex库实例用法总结
Jan 03 Python
python opencv人脸识别考勤系统的完整源码
Apr 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 CURL用法的深入分析
2013/06/09 PHP
网站防止被刷票的一些思路与方法
2015/01/08 PHP
php将图片保存为不同尺寸图片的图片类实例
2015/03/30 PHP
php对文件进行hash运算的方法
2015/04/03 PHP
jQuery之过滤元素操作小结
2013/11/30 Javascript
javascript轻量级模板引擎juicer使用指南
2014/06/22 Javascript
node.js中的console用法总结
2014/12/15 Javascript
Jquery插件实现点击获取验证码后60秒内禁止重新获取
2015/03/13 Javascript
javascript字符串循环匹配实例分析
2015/07/17 Javascript
js+css实现文字散开重组动画特效代码分享
2015/08/21 Javascript
js读取并解析JSON类型数据的方法
2015/11/14 Javascript
基于JS实现数字+字母+中文的混合排序方法
2016/06/06 Javascript
浅谈react受控组件与非受控组件(小结)
2018/02/09 Javascript
js实现for循环跳过undefined值示例
2019/07/02 Javascript
在pycharm中开发vue的方法步骤
2020/03/04 Javascript
js 数据类型判断的方法
2020/12/03 Javascript
[01:15:45]DOTA2上海特级锦标赛B组小组赛#1 Alliance VS Spirit第一局
2016/02/26 DOTA
Python的类实例属性访问规则探讨
2015/01/30 Python
Python基于PycURL实现POST的方法
2015/07/25 Python
python文件拆分与重组实例
2018/12/10 Python
PYTHON EVAL的用法及注意事项解析
2019/09/06 Python
python selenium实现发送带附件的邮件代码实例
2019/12/10 Python
基于python 凸包问题的解决
2020/04/16 Python
keras 使用Lambda 快速新建层 添加多个参数操作
2020/06/10 Python
Python 如何展开嵌套的序列
2020/08/01 Python
requests在python中发送请求的实例讲解
2021/02/17 Python
C++如何引用一个已经定义过的全局变量
2014/08/25 面试题
外贸业务员求职自荐信分享
2013/09/21 职场文书
学生会招新策划书
2014/02/14 职场文书
《大自然的语言》教学反思
2014/04/08 职场文书
端午节活动总结
2014/08/26 职场文书
诉讼代理人授权委托书
2014/10/11 职场文书
政府会议通知范文
2015/04/15 职场文书
python实现自动化群控的步骤
2021/04/11 Python
Vue项目中如何封装axios(统一管理http请求)
2021/05/02 Vue.js
CSS 实现角标效果的完整代码
2022/06/28 HTML / CSS