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中将函数赋值给变量时需要注意的一些问题
Aug 18 Python
git进行版本控制心得详谈
Dec 10 Python
Python将图片转换为字符画的方法
Jun 16 Python
python判断文件夹内是否存在指定后缀文件的实例
Jun 10 Python
解决Python3 抓取微信账单信息问题
Jul 19 Python
Python3 翻转二叉树的实现
Sep 30 Python
Python 模拟动态产生字母验证码图片功能
Dec 24 Python
对Tensorflow中tensorboard日志的生成与显示详解
Feb 04 Python
python使用hdfs3模块对hdfs进行操作详解
Jun 06 Python
拿来就用!Python批量合并PDF的示例代码
Aug 10 Python
Django修改app名称和数据表迁移方案实现
Sep 17 Python
Python爬虫入门教程02之笔趣阁小说爬取
Jan 24 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中iconv函数使用方法
2008/05/24 PHP
PHP 开源AJAX框架14种
2009/08/24 PHP
php使用curl和正则表达式抓取网页数据示例
2014/04/13 PHP
php获取网页中图片、DIV内容的简单方法
2014/06/19 PHP
PHP数据库表操作的封装类及用法实例详解
2016/07/12 PHP
php使用socket调用http和smtp协议实例小结
2019/07/26 PHP
JS处理VBArray的函数使用说明
2008/05/11 Javascript
Javascript中的Array数组对象详谈
2014/03/03 Javascript
jQuery scroll事件实现监控滚动条分页示例
2014/04/04 Javascript
jQuery循环滚动新闻列表示例代码
2014/06/17 Javascript
JS的事件绑定深入认识
2014/06/26 Javascript
js使用post 方式打开新窗口
2015/02/26 Javascript
Express的路由详解
2015/12/10 Javascript
浅述节点的创建及常见功能的实现
2016/12/15 Javascript
原生JS实现在线问卷调查投票特效
2017/01/03 Javascript
ES6新数据结构Set与WeakSet用法分析
2017/03/31 Javascript
微信小程序引用公共js里的方法的实例详解
2017/08/17 Javascript
sublime text配置node.js调试(图文教程)
2017/11/23 Javascript
vue实现微信分享功能
2018/11/28 Javascript
Node.js折腾记一:读指定文件夹,输出该文件夹的文件树详解
2019/04/20 Javascript
javascript刷新父页面方法汇总详解
2019/10/10 Javascript
Vue extend的基本用法(实例详解)
2019/12/09 Javascript
H5实现手机拍照和选择上传功能
2019/12/18 Javascript
小程序实现上传视频功能
2020/08/18 Javascript
详解pandas的外部数据导入与常用方法
2019/05/01 Python
对python3 sort sorted 函数的应用详解
2019/06/27 Python
python爬取本站电子书信息并入库的实现代码
2020/01/20 Python
Python控制台输出时刷新当前行内容而不是输出新行的实现
2020/02/21 Python
HTML5的文档结构和新增标签完全解析
2017/04/21 HTML / CSS
美国宠物商店:Wag.com
2016/10/25 全球购物
JAVA的事件委托机制和垃圾回收机制
2014/09/07 面试题
党的群众路线调研报告
2014/11/03 职场文书
简历中的自我评价应该这样写!
2019/07/12 职场文书
vue生命周期钩子函数以及触发时机
2022/04/26 Vue.js
Android开发手册TextInputLayout样式使用示例
2022/06/10 Java/Android
js面向对象编程OOP及函数式编程FP区别
2022/07/07 Javascript