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的Flask框架中web表单的教程
Apr 20 Python
python使用fileinput模块实现逐行读取文件的方法
Apr 29 Python
Python中datetime模块参考手册
Jan 13 Python
python3+PyQt5实现拖放功能
Apr 24 Python
python 自定义异常和异常捕捉的方法
Oct 18 Python
Django中如何防范CSRF跨站点请求伪造攻击的实现
Apr 28 Python
Django 开发环境配置过程详解
Jul 18 Python
django 类视图的使用方法详解
Jul 24 Python
基于python生成英文版词云图代码实例
May 16 Python
记录一下scrapy中settings的一些配置小结
Sep 28 Python
Python 实现一个简单的web服务器
Jan 03 Python
Pillow图像处理库安装及使用
Apr 12 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
ThinkPHP php 框架学习笔记
2009/10/30 PHP
linux系统上支持php的 iconv()函数的方法
2011/10/01 PHP
php实现中文转数字
2016/02/18 PHP
php使用ffmpeg获取视频信息并截图的实现方法
2016/05/03 PHP
php支付宝在线支付接口开发教程
2016/09/19 PHP
javascript parseInt与Number函数的区别
2010/01/21 Javascript
jquery 无限级联菜单案例分享
2013/03/26 Javascript
Jquery解析json数据详解
2013/12/26 Javascript
使用jQuery实现图片遮罩半透明坠落遮挡
2015/03/16 Javascript
jQuery实现自动滚动到页面顶端的方法
2015/05/22 Javascript
jQuery validate验证插件使用详解
2016/05/11 Javascript
jQuery封装的屏幕居中提示信息代码
2016/06/08 Javascript
js异步编程小技巧详解
2017/08/14 Javascript
Element-ui之ElScrollBar组件滚动条的使用方法
2018/09/14 Javascript
js字符串倒序的实例代码
2018/11/30 Javascript
基于Vue 实现一个中规中矩loading组件
2019/04/03 Javascript
vuex管理状态 刷新页面保持不被清空的解决方案
2019/11/11 Javascript
详谈Python基础之内置函数和递归
2017/06/21 Python
pandas 取出表中一列数据所有的值并转换为array类型的方法
2018/04/11 Python
原来我一直安装 Python 库的姿势都不对呀
2019/11/11 Python
django商品分类及商品数据建模实例详解
2020/01/03 Python
python 中的paramiko模块简介及安装过程
2020/02/29 Python
Django 删除upload_to文件的步骤
2020/03/30 Python
Python tkinter制作单机五子棋游戏
2020/09/14 Python
突袭HTML5之Javascript API扩展1—Web Worker异步执行及相关概述
2013/01/31 HTML / CSS
美国知名的隐形眼镜电商:Contacts America
2019/11/19 全球购物
秋季运动会活动方案
2014/02/05 职场文书
工伤事故赔偿协议书
2014/10/27 职场文书
专业见习报告范文
2014/11/03 职场文书
2015年乡镇纪检工作总结
2015/04/22 职场文书
赡养老人协议书范本
2015/08/06 职场文书
2016年清明节网上祭英烈活动总结
2016/04/01 职场文书
周一早安温馨问候祝福语!
2019/07/15 职场文书
2019最新版股权转让及委托持股协议书范本
2019/08/07 职场文书
JAVA API 实用类 String详解
2021/10/05 Java/Android
Python中的turtle画箭头,矩形,五角星
2022/03/16 Python