资讯专栏INFORMATION COLUMN

Python进程专题7:托管对象

DevYK / 2292人阅读

摘要:连接带远程管理器对象,该对象的地址在构造函数中支出。在当前进程中运行管理器服务器。启动一个单的子进程,并在该子进程中启动管理器服务器。如果无法序列号对象将引发异常。

上一篇文章:Python进程专题6:共享数据与同步
下一篇文章:Python进程专题8:分布集群的消息传递
进程不支持共享对象,上面描述的创建共享值和数组,但都是指定的特殊类型,对高级的Python对象(如:字典、列表、用户自定义类的实例)不起作用。

还好multiprocessing模块提供了一种使用共享对象的途径:单前提是这些对象运行在所谓的【管理器】的控制之下。

管理器是独立的子进程,其中存在真实的对象,并以服务器的形式运行,其他进程通过使用代理访问共享对象,这些

代理作为管理器服务器的客户端而运行。

语法:
m=Manager():在一个独立的进程中创建运行的管理器,返回值是SyncManager(定义在multiprocess.managersa模块中)类的实例。
m可以创建共享对象
常用方法

m.Array(typecode,sequence)

在服务器上创建共享的Array实例并返回可以访问它的代理。

m.BoundedSemaphore(value)

在服务器上创建共享的threading.BoundedSemphore实例,并返回可访问它的代理。

m.Condition(lock)

在服务器上创建共享的threading.Condition实例,并返回可访问它的代理。
lock是m.Lock()或m.Rlock()方法创建的代理实例

m.dict(args)

在服务器上创建共享的dict(字典)实例,并返回可以访问它的代理。

m.Event()

在服务器上创建共享的thread.Event实例,并返回可以访问它的代理。

m.list(sequence)

在服务器上创建共享的list实例,并返回可以访问它的代理。

m.Lock

子服务器上创建共享的threading.Lock实例,并返回可访问它的代理。

m.Namespace()

在服务器创建共享的namespace对象,并返回可以访问它的代理。
namespace就是一个类似于Python模块的对象。例如:如果n是一个命名空间代理,那么可以使用(.)赋值和读取属性,
例如:n.name=value 或value=n.name。但name的名称十分重要,如果name以字母开头,那么这个值就是管理器所拥有的共享对象的一部分,
所有其它进程均可访问它,如果name以下划线开头,那么它只是代理对象的一部分,并不是共享。

m.Queue()

在服务器上创建共享的Queue.Queue对象,并返回可访问它的代理。

m.RLock()

在服务器上创建共享的threading.Rlick对象,并返回可访问它的代理。

m.Semaphore(value)

在服务器上创建共享的threading.Semaphore对象,并返回可访问它的代理。

m.value(typecode,value)

在服务器上创建一个共享的Value对象,并返回可访问它的代理。

实例1使用管理者创建一个在进程中共享的字典:

代码:
#使用管理器创建一个在进程间共享的字典

import multiprocessing
import time

def watch(dict,event):
    while True:
        event.wait()
        print(dict)
        event.clear()


if __name__=="__main__":
    #实例化一个管理器
    m=multiprocessing.Manager()
    #在服务器上创建一个共享的字典,并返回可以调用它的代理
    dict=m.dict()
    #在服务器上创建一个共享的Event
    event=m.Event()

    #启动监视字典的进程
    p=multiprocessing.Process(target=watch,args=(dict,event,))
    #设置为后台进程,随主进程的销毁而销毁,该后台进程无法创建新的线程
    p.daemon=True
    p.start()

    #更新字典并通知监听者
    dict["name"]="mark"
    event.set()
    time.sleep(3)

    # 更新字典并通知监听者
    dict["age"] = 18
    event.set()
    time.sleep(3)


    #终止进程和管理器
    p.terminate()

    m.shutdown()

运行结果:

继承BaseManager类,实现自定义对象的共享
如果想要共享用户自定义类的实例,则必须创建自定义管理器对象,为此,需要创建一个继承自BaseManager类的类,

其中BaseManager类定义在multiprocessing.managers子模块中。

语法:

managers.BaseManager(address,authkey):用户自定对象创建管理器服务器的基类。
address是一个可选的元组(hostname,port),用于指定服务器的网络地址。如果忽略此参数,操作系统将简单
的分配一个对应于某些空闲端口号的地址。
authkey是一个字符串,用于对连接到服务器的客户端身份进行验证。如果忽略此参数,将是哟个current_process().authkey的值。

假设myclass是一个继承自BaseManager的类,可以使用以下类方法来创建用于返回代理给共享对象的方法。

myclass.register(typeid,callable,proxytype,exposed,method_to_typeid,create_method):使用管理器类注册一种新的数据类型。

typeid:一个字符串,用于命名特殊类型的共享对象。这个字符串应该是有效的Python标识符。

callable:创建或返回要共享的实例的可调用对象。

proxytype:一个类,负责提供客户端中药使用的代理对象的实现,通常这些类是默认生成的,因此一般设置为None。
exposed:共享对象上方法名的序列,它将会公开给代理对象,如果省略此参数,将使用proxytype_exposed的值,
如果proxytype_expose未定义,序列将包含所有的公共方法(所有不以下划线_开头的可调用方法)。

method_to_typeid:从方法名称到类型IDS的映射,这里的IDS用于指定哪些方法应该使用代理对象返回他们的结果,
如果某个方法在这个映射中找不到,将复制和返回它的返回值,如果method_to_typeid为None,将使用proxytype_method_to_typeid_的值。

create_method:一个布尔标志,用于指定是否在mgclass中创建名为typeid的方法,默认值为True。

从BaseManager类派生的管理器的实例m必须手动启动才能运行。

属性于常用方法

属性或者方法 解释说明
m.address 元组(hostname,port),代表管理器服务器正在使用的地址。
m.connect() 连接带远程管理器对象,该对象的地址在BaseManager构造函数中支出。
m.serve_forever() 在当前进程中运行管理器服务器。
m.shutdown() 关闭由start()启动的管理器服务器。
m.start() 启动一个单的子进程,并在该子进程中启动管理器服务器。

继承自BaseProxy的类的实例具有以下方法:

proxy._callmethod(name,args,kwargs):调用代理引用对象上的方法name。

proxy._getvalue():返回调用者中引用对象的副本,如果这次调用是在另一个进程中,
那么引用对象将被序列化,发送给调用者,然后再进行反序列化。如果无法序列号对象将引发异常。

代码:

#继承BaseManager类,实现自定义对象的共享,利用代理公开属性与方法
import multiprocessing
from multiprocessing.managers import  BaseManager
from multiprocessing.managers import  BaseProxy

#普通需要共享的类,代理无法通过(.)这种形式直接访问属性
class MyClass():
    def __init__(self,value):
        self.name=value

    def __repr__(self):
        return "MyClass(%s)"%self.name

    def getName(self):
        return self.name
    def setName(self,value):
        self.name=value

    def __add__(self,valuye):
        self.name+=valuye
        return self

#通过自定义继承BaseProxy来实现代理,从而正确的公开__add__方法,并使用特性(property)公开name属性。
#BaseProxy来来自multiprocessing.managers模块
class MyClassProxy(BaseProxy):
    #referent上公开的所有方法列表
    _exxposed_=["__add__","getName","setName"]
    #实现代理的公共结接口
    def __add__(self, value):
        self._callmethod("__add__",(value,))
        return self
    @property
    def name(self):
        return self._callmethod("getName",())
    @name.setter
    def name(self,value):
        self._callmethod("setName",(value,))


    def __repr__(self):
        return "MyClass(%s)"%self.name

    def getName(self):
        return self.name
    def setName(self,value):
        self.name=value

    def __add__(self,valuye):
        self.name+=valuye
        return self

class MyManager(BaseManager):
    pass

#不使用代理
#MyManager.register("MyClass",MyClass)
#使用代理
MyManager.register("MyClass",MyClass,proxytype=MyClassProxy)

if __name__=="__main__":
    m=MyManager()
    m.start()

    #创建托管对象,此时知识创建了一个实例代理,无法直接访问属性,必须使用函数来访问
    #代理无法访问特殊方法和下划线(_)开头的所有方法。
    a=m.MyClass("mark")
    print(a)
    print(a.getName())

    #不使用代理,下面两条语句会异常
    a.__add__("帅哥")
    print(a.name)

    #print(a.name)
    #a.__add__("帅哥")

结果:

MyClass(mark)
mark
mark帅哥

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/42354.html

相关文章

  • Python进程专题6:共享数据与同步

    摘要:可以使用标准的索引切片迭代操作访问它,其中每项操作均锁进程同步,对于字节字符串,还具有属性,可以把整个数组当做一个字符串进行访问。当所编写的程序必须一次性操作大量的数组项时,如果同时使用这种数据类型和用于同步的单独大的锁,性能将极大提升。 上一篇文章:Python进程专题5:进程间通信下一篇文章:Python进程专题7:托管对象 我们现在知道,进程之间彼此是孤立的,唯一通信的方式是队...

    Yuanf 评论0 收藏0
  • Python进程专题8:分布集群的消息传递

    摘要:代表网络地址的元组或者代表域套接字的文件名,或者代表形式的字符串,代表远程系统本地计算机的为上的一条命名管道。是一个整数,当参数指定了一个网络连接时,对应于传递给套接字的方法的值,默认为。 上一篇文章:Python进程专题7:托管对象下一篇文章:Python进程专题9:关于进程的实用工具函数 使用multiprocessing模块的程序不仅可以于运行在同一计算机的其它程序进行消息传递...

    wh469012917 评论0 收藏0
  • Python线程专题纵览篇

    摘要:上一篇文章进程专题完结篇多进程处理的一般建议下一篇文章线程专题多线程使用的必要性进程线程进程能够完成多任务,比如在一个电脑上可以运行多个软件。由于占用资源少,也使得多线程程序并发比较高。 上一篇文章:Python进程专题完结篇:多进程处理的一般建议下一篇文章:Python线程专题1:多线程使用的必要性 进程VS线程 进程:能够完成多任务,比如在一个电脑上可以运行多个软件。线程:也能够...

    张红新 评论0 收藏0
  • Python进程专题4:进程池Pool

    摘要:上一篇文章进程专题继承来创建进程下一篇文章进程专题进程间通信当我们需要创建大量的进程时,利用模块提供的来创建进程。关闭进程池,不再接受进的进程请求,但已经接受的进程还是会继续执行。 上一篇文章:Python进程专题3:继承Process来创建进程下一篇文章:Python进程专题5:进程间通信 当我们需要创建大量的进程时,利用multiprocessing模块提供的Pool来创建进程。 ...

    Leo_chen 评论0 收藏0
  • Python进程专题9:关于进程的实用工具函数

    摘要:上一篇文章进程专题分布集群的消息传递下一篇文章进程专题函数解析返回所有活动子进程的对象组成的列表返回系统上的数量,如果能够确定的话返回当前进程的对象在实用各种打包工具如进行冻结的应用程序中,次函数应该作为主程序的首行。 上一篇文章:Python进程专题8:分布集群的消息传递下一篇文章:Python进程专题10:GIL 函数 解析 activite_children() 返回...

    妤锋シ 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<