简体   繁体   English

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

[英]python multiprocessing: How to modify a dictionary created in the main process from a subprocess?

This question is related to: multiprocessing: How do I share a dict among multiple processes?这个问题与: multiprocessing: How do I share a dict 在多个进程之间?

I have multiple numpy arrays stored in a multiprocessing Dict.我在多处理字典中存储了多个 numpy 数组。 The multiprocessing dict is declared and populated with numpy arrays at predefined keys.多处理 dict 在预定义的键处声明并填充有 numpy 数组。 each subprocess only writes and modifies data in a single key of the dict.每个子进程仅在 dict 的单个键中写入和修改数据。 The dictionary isnt updated by the subprocesses even thought the subprocesses seem to do something(shouldn't the dictionary be modified "inplace", at the memory location of the dictionary declared in the main process?).即使认为子进程似乎在做某事,字典也不会被子进程更新(不应该在主进程中声明的字典的内存位置“就地”修改字典吗?)。

I do not understand why it isn't working;我不明白为什么它不起作用; is the data contained in the dict copied to each subprocess then modified in it and not returned to the main process? dict 中包含的数据是否被复制到每个子进程然后在其中修改而不返回到主进程? if that's the case, is there a way to modify the data without copying it somewhere else?如果是这种情况,有没有办法修改数据而不将其复制到其他地方? In multiprocessing there may be a problem with unwanted data deletion when multiple processes try to write to the same adress, in my case, since each subprocess only writes to a specific key, will this unwanted data deletion be a problem?在多处理中,当多个进程尝试写入同一个地址时,可能会出现不需要的数据删除问题,在我的情况下,由于每个子进程只写入一个特定的键,这种不需要的数据删除会成为问题吗?

Sample code:示例代码:

    
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)

prints: TIK and TOK randomly (as expected) and打印: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)}

is returned被退回

This is due to the way the Manager() manages the dict .这是由于Manager()管理dict Only the dict itself is managed, not its entries (unless the entries happen to be Proxy Objects ).仅管理dict本身,而不管理其条目(除非条目恰好是Proxy Objects )。 Thus when working with mutable dict entries, updates to the objects are not handled (or even registered) by the manager.因此,当使用可变 dict 条目时,管理器不会处理(甚至注册)对象的更新。

However, it is possible to update the dict itself, eg by replacing a full dict entry.但是,可以更新 dict 本身,例如通过替换完整的dict条目。 Thus, a way to get around the above limitation, is to get a local reference to the entry, update it, and then re-assign the local reference to the managed dict .因此,绕过上述限制的一种方法是获取对条目的本地引用,更新它,然后将本地引用重新分配给托管dict

In this particular case, it would mean that the appenddict function has to be modified slightly:在这种特殊情况下,这意味着必须稍微修改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

With these changes, your program ought to work more as you expect it to.通过这些更改,您的程序应该可以按您的预期运行更多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM