python multiprocessing:如何从子进程修改在主进程中创建的字典?

Posted

技术标签:

【中文标题】python multiprocessing:如何从子进程修改在主进程中创建的字典?【英文标题】:python multiprocessing: How to modify a dictionary created in the main process from a subprocess? 【发布时间】:2020-12-24 11:25:24 【问题描述】:

此问题与:multiprocessing: How do I share a dict among multiple processes?

我有多个 numpy 数组存储在多处理字典中。多处理 dict 被声明并在预定义的键处使用 numpy 数组填充。每个子进程只在字典的单个键中写入和修改数据。即使子进程似乎在做某事,子进程也不会更新字典(不应该在主进程中声明的字典的内存位置“就地”修改字典吗?)。

我不明白为什么它不起作用; dict中包含的数据是否复制到每个子进程然后在其中修改而不返回到主进程?如果是这种情况,有没有办法修改数据而不将其复制到其他地方?在多处理中,当多个进程尝试写入同一个地址时,可能会出现不需要的数据删除问题,在我的情况下,由于每个子进程只写入特定的键,这种不需要的数据删除会成为问题吗?

示例代码:

    
import datetime
import numpy as np
import random
from multiprocessing import Process,Manager

class nbrgen(object):
    def __init__(self,ticker,TBA,delay):
        self.delay=delay
        self.value=100.00
        self.volume=50
        self.ticker=ticker
        self.TBA=TBA

    def generate_value(self):
        self.value=round (self.value + random.gauss(0,1)*self.delay + 0.01 ,2)
        self.volume=random.randint(1,100)

    def __next__(self):
        return self.next()

    def next(self):
        self.generate_value()
        t=datetime.datetime.now(tz=datetime.timezone.utc)
        return np.array([t,self.ticker,self.TBA,self.value,self.volume])

    def apenddict(D, tik,gnr):
      for i in range(8):
        print(tik)
        D[tik][:-1] = D[tik][1:]
        D[tik][-1:, :] = gnr.next()


    if __name__ =="__main__":
     manager=Manager()
     d=manager.dict()
     d["TOK"] = np.zeros((10, 5), dtype="O")
     d["TIK"] = np.zeros((10, 5), dtype="O")
 
     p1=Process(target=apenddict,args=(d,"TIK",nbrgen("TIK","T",0.1)))
     p2=Process(target=apenddict,args=(d,"TOK",nbrgen("TOK","T",0.1)))

     p1.start()
     p2.start()
     p1.join()
     p2.join()

     print(d)

打印:TIK 和 TOK 随机(如预期)和

'TOK': array([[0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0]], dtype=object), 'TIK': array([[0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0]], dtype=object)

返回

【问题讨论】:

【参考方案1】:

这是由于Manager() 管理dict 的方式。只有dict 本身被管理,而不是它的条目(除非条目恰好是Proxy Objects)。因此,在使用可变 dict 条目时,管理器不会处理(甚至注册)对象的更新。

但是,可以更新 dict 本身,例如通过替换完整的dict 条目。因此,绕过上述限制的一种方法是获取对条目的本地引用,对其进行更新,然后将本地引用重新分配给托管dict

在这种特殊情况下,这意味着必须稍微修改appenddict 函数:

def apenddict(D, tik,gnr):
    tik_array = D[tik]  # Create local reference
    for i in range(8):
        print(tik)
        tik_array[:-1] = D[tik][1:]  # Update local reference
        tik_array[-1:, :] = gnr.next()  # Update local reference
    D[tik] = tik_array  # Assign local reference to managed dict

通过这些更改,您的程序应该可以按照您的预期工作。

【讨论】:

以上是关于python multiprocessing:如何从子进程修改在主进程中创建的字典?的主要内容,如果未能解决你的问题,请参考以下文章

(Python 多处理)如何访问与 multiprocessing.shared_memory.SharedMemory 共享的数组?

Python:如何检查 multiprocessing.Pool 中待处理任务的数量?

python multiprocessing:如何从子进程修改在主进程中创建的字典?

如何使用 Pythons Multiprocessing 库的 Process 类多次运行一个函数?

如何检查 Python Multiprocessing 中的 Process 类是不是有效?

Python Multiprocessing:如何将其保存在指定的函数中?