• Python通过Manager方式实现多个无关联进程共享数据


    Python实现多进程间通信的方式有很多种,例如队列,管道等。
    但是这些方式只适用于多个进程都是源于同一个父进程的情况。
    如果多个进程不是源于同一个父进程,只能用共享内存,信号量等方式,但是这些方式对于复杂的数据结构,例如Queue,dict,list等,使用起来比较麻烦,不够灵活。
    Manager是一种较为高级的多进程通信方式,它能支持Python支持的的任何数据结构。
    它的原理是:先启动一个ManagerServer进程,这个进程是阻塞的,它监听一个socket,然后其他进程(ManagerClient)通过socket来连接到ManagerServer,实现通信。

    manager.py代码,实现server和client两个类

    # encoding=utf-8
    __author__ = 'kevinlu1010@qq.com'
    '''
    进程间通信
    '''
    from multiprocessing.managers import BaseManager
    from multiprocessing import RLock
    
    MANAGER_PORT = 6000
    MANAGER_DOMAIN = '0.0.0.0'
    MANAGER_AUTH_KEY = 'aaaaaaaaaaaaaaa'
    
    #定义一个Manager类
    class InfoManager(BaseManager): pass
    
    
    class DictItem():
        def __init__(self, ):
            self.items = dict()
    
        def set(self, key, value):
            self.items[key] = value
    
        def get(self, key):
            return self.items.get(key)
    
        def __setitem__(self, key, value):
            self.set(key, value)
    
    #为这个manager类注册存储容器,也就是通过这个manager类实现的共享的变量,
    #这个变量最好是一个类实例,自己定义的或者python自动的类的实例都可以
    #这里不能把d改成dict(),因为Client那边执行d['keyi']='value'的时候会报错:d这个变量不能修改
    d = DictItem()
    lock = RLock()
    InfoManager.register('dict', callable=lambda: d)
    InfoManager.register('open_qq_login_lock', callable=lambda: lock)
    
    
    class ManagerServer():
        '''
        multiprocess Manager服务类
        '''
    
        def __init__(self, domain, port, auth_key):
            self.domain = domain
            self.port = port
            self.auth_key = auth_key
    
        def start_manager_server(self):
            self.queue_manager = InfoManager(address=('', self.port), authkey=self.auth_key)
            # self.dict = self.queue_manager.dict()
            self.server = self.queue_manager.get_server()
    
        def run(self):
            self.start_manager_server()
            self.server.serve_forever()
    
        def stop(self):
            self.server.shutdown()
            self.is_stop = 1
    
    
    class ManagerClient():
        '''
        访问mutiprocess Manager的类
        '''
    
        def __init__(self, domain, port, auth_key):
            self.domain = domain
            self.port = port
            self.auth_key = auth_key
            # self.get_share_dict()
            self.info_manager = InfoManager(address=(self.domain, self.port), authkey=self.auth_key)
            self.info_manager.connect()
    
        def get_dict(self):
            # self.dict = m.dict()
            self.dict = self.info_manager.dict()
            return self.dict
    
        def get_open_qq_login_lock(self):
            self.open_qq_login_lock = self.info_manager.open_qq_login_lock()
            return self.open_qq_login_lock
    
    
    if __name__ == '__main__':
        pass

    用法
    1.启动一个ManagerServer,这个进程是阻塞的

    import manager
    
    def run():
        manager_server = manager.ManagerServer(manager.MANAGER_DOMAIN, manager.MANAGER_PORT, manager.MANAGER_AUTH_KEY)
        manager_server.run()
    if __name__ == '__main__':
        run()

    2.实例化一个client,获取共享的变量

    # 进程间共享变量
    manager_client = manager.ManagerClient(manager.MANAGER_DOMAIN, manager.MANAGER_PORT, manager.MANAGER_AUTH_KEY)
    share_dict = manager_client.get_dict()
    open_qq_login_lock = manager_client.get_open_qq_login_lock()

    注意:
    1.对client获取的变量修改,不会影响server那边的变量,例如server中,client1获取变量params1,把它修改为params2,server那边的数据不会修改。如果要修改server的数据,需要调用server的方法,把server那边的数据刷新。

  • 相关阅读:
    设计模式工厂模式
    设计模式原型模式
    Excel自定义格式千分符
    浏览器报:net::ERR_EMPTY_RESPONSE解决方案
    git branch a无法显示远程分支解决办法
    .Net启动程序报错:It was not possible to find any compatible framework version
    自动化测试框架pytest 安装和入门到精通实战
    2020非常全的接口测试面试题及参考答案软件测试工程师没有碰到算我输!
    Python+unittest+requests+excel实现接口自动化测试框架项目实战
    软件测试必学之python+unittest+requests+HTMLRunner编写接口自动化测试集
  • 原文地址:https://www.cnblogs.com/ExMan/p/10187577.html
Copyright © 2020-2023  润新知