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脚本设置超时机制系统时间的方法
Feb 21 Python
Python的Flask框架中使用Flask-Migrate扩展迁移数据库的教程
Jun 14 Python
Python中单例模式总结
Feb 20 Python
Django forms组件的使用教程
Oct 08 Python
Python实现将通信达.day文件读取为DataFrame
Dec 22 Python
使用python爬取微博数据打造一颗“心”
Jun 28 Python
利用keras加载训练好的.H5文件,并实现预测图片
Jan 24 Python
Django实现微信小程序支付的示例代码
Sep 03 Python
python对输出的奇数偶数排序实例代码
Dec 04 Python
PyQt5 显示超清高分辨率图片的方法
Apr 11 Python
Django与数据库交互的实现
Jun 03 Python
python双向链表实例详解
May 25 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/03/04 PHP
来自phpguru得Php Cache类源码
2010/04/15 PHP
PHP去掉从word直接粘贴过来的没有用格式的函数
2012/10/29 PHP
深入剖析浏览器退出之后php还会继续执行么
2016/05/17 PHP
php reset() 函数指针指向数组中的第一个元素并输出实例代码
2016/11/21 PHP
Laravel jwt 多表(多用户端)验证隔离的实现
2019/12/18 PHP
动手学习无线电
2021/03/10 无线电
使用Jquery获取带特殊符号的ID 标签的方法
2014/04/30 Javascript
jQuery照片伸缩效果不影响其他元素的布局
2014/05/09 Javascript
node.js中的fs.renameSync方法使用说明
2014/12/16 Javascript
自己动手写的javascript前端等待控件
2015/10/30 Javascript
AnjularJS中$scope和$rootScope的区别小结
2016/09/18 Javascript
详解jQuery的Cookie插件
2016/11/23 Javascript
关于JS Lodop打印插件打印Bootstrap样式错乱问题的解决方案
2016/12/23 Javascript
基于jQuery实现的Ajax 验证用户名唯一性实例代码
2017/06/28 jQuery
详谈表单重复提交的三种情况及解决方法
2017/08/16 Javascript
Node.js使用cookie保持登录的方法
2018/05/11 Javascript
发布Angular应用至生产环境的方法
2018/12/10 Javascript
微信小程序实现带参数的分享功能(两种方法)
2019/05/17 Javascript
layui前端时间戳转化实例
2019/11/15 Javascript
Python爬虫实现抓取京东店铺信息及下载图片功能示例
2018/08/07 Python
使用Python Pandas处理亿级数据的方法
2019/06/24 Python
浅析Python 引号、注释、字符串
2019/07/25 Python
Pandas实现dataframe和np.array的相互转换
2019/11/30 Python
python实现银行实战系统
2020/02/26 Python
解决json中ensure_ascii=False的问题
2020/04/03 Python
python框架flask入门之环境搭建及开启调试
2020/06/07 Python
Python 用__new__方法实现单例的操作
2020/12/11 Python
IMPORT的选项IGNORE有什么作用?缺省是什么设置?
2015/09/17 面试题
大学生求职信范文应怎么写
2014/01/01 职场文书
护士辞职信模板
2014/01/20 职场文书
安全生产承诺书范文
2014/05/22 职场文书
应届毕业生求职信范文
2014/07/07 职场文书
十八大标语口号
2014/10/09 职场文书
2014年教师个人工作总结
2014/11/10 职场文书
叶问观后感
2015/06/15 职场文书