使用多处理在类内共享属性

问题描述

我有一个以字典为属性的类。在这个类中,我运行multiprocessing来填写Queue,然后使用其他过程对Queue中的项执行一些计算。当满足条件时,我将结果存储在此词典中,但我发现当进程希望在词典中存储值时,词典键不在词典中。

class RNG():
    def __init__(self):
        self.mydict = {}
        self.done = False
        self.q = Queue(maxsize = 100)
        self.lock = Lock()
        
    def _fill_queue(self):
        while not self.done:
            rng = randint(1,9e6)
            
            if rng % 2 ==0:
                _type = 'even'
                if 'even' not in self.mydict.keys():
                    self.mydict['even'] = []
            else:
                _type = 'odd'
                if 'odd' not in self.mydict.keys():
                    self.mydict['odd'] = []
                    
            while self.q.full():
                sleep(10)
            
            self.lock.acquire()
            self.q.put((_type,rng))
            self.lock.release()
            
    def _process_queue(self):
        while not self.done:
            self.lock.acquire()
            if self.q.empty():
                self.lock.release()
                continue
                
            _type,num = self.q.get()
            self.lock.release()
            
            print(f'Appending {_type} number!')
            self.mydict[_type].append(num)
            self._check_for_exit()
            
    def _check_for_exit(self):
        if len(self.mydict['odd']) >= 1e6 and len(self.mydict['even'])>=1e6:
            self.done = True
    
    def run(self):
        jobs = []
        p = Process(target = self._fill_queue)
        jobs.append(p)
        p.start()
        for _ in range(5):
            p = Process(target = self._process_queue)
            jobs.append(p)
            p.start()
            
        for job in jobs:
            job.join()
        
if __name__ == '__main__':
    rng = RNG()
    rng.run()
     

当我运行此命令时,尝试在词典中追加数字时出现以下错误:

KeyError: 'even'
KeyError: 'odd'

为什么没有将密钥添加到词典中?另外,如果每个进程都设法写入一个文件,并且该文件具有相同的名称,这是否意味着我需要实现某种信号量或Pipe


解决方案

请记住,它们作为两个单独的进程运行。它们并不共享内存。每一个都有自己的RNG实例副本,不会看到对方所做的更改。如果您需要在它们之间进行通信,则需要使用队列或管道。

通常,多处理应用程序要做的是建立一个在它们之间传递的命令和对象。该命令有某种动词,外加要操作的数据。所以,当你想要添加一个密钥时,你可以发送(‘Add’,‘Even’)或类似的东西。然后,您的队列处理程序可以执行几种不同的操作。

相关文章