1

가 나는 dictdict를 업데이트하고 싶었 외부 사람은 multiprocessing.Manager()를 통해 인스턴스화 :Manager() 인 이유 dict()가 한 수준 만 업데이트 되었습니까?

import multiprocessing 

def worker(key, container): 
    # this one is not applied 
    container['a'][key] = key 
    # this one is 
    container[key] = 3 

if __name__ == "__main__": 
    multiprocessing.freeze_support() 

    c = multiprocessing.Manager().dict() 
    c['a'] = {} 

    p1 = multiprocessing.Process(target=worker, args=('x',c,)) 
    p2 = multiprocessing.Process(target=worker, args=('y',c,)) 

    p1.start() 
    p2.start() 
    p1.join() 
    p2.join() 
    print(c.copy()) 

이 코드의 출력은 내가

{'y': 3, 'a': {'x': 'x', 'y': 'y'}, 'x': 3} 
을받을 것으로 예상

{'y': 3, 'a': {}, 'x': 3} 

입니다

dict의 첫 번째 레벨은에서 처리 할 수 ​​있습니다.이지만 중첩 된 dict의 작업은 무시됩니다. 왜?

나는 처음에이 얕은 복사가 원인 일의 나이라고 생각하지만, copy.deepcopy()

답변

1

Managerdict 객체의 로컬 버전을 유지하고 Manager없이 객체의 행동을 모방하는 프록시 기능을 제공하는 서브 프로세스를 사용하여 구현되는 출력한다.
container['a']을 호출하면 'a' 키와 연결된 값의 로컬 복사본을 반환하는 프록시 함수를 사용합니다. 따라서 하위 프로세스 중 하나에서이 복사본을 수정하면 변경 내용은 로컬에만 적용됩니다. 당신이 세계 변화를 원하는 경우, 다음 중 하나를 수행 할 수 있습니다 :

  • 는 로컬 복사본을 수정하고 제안 된 set의 프록시, container['a'] = new_dict를 사용하여 동기화 할 수 있습니다. 불편한 점은 원자가 아니므로 p1p2이 사전을 얻는 것처럼 동시성 문제가 발생한다는 것입니다. 둘 다 {}을 얻게되고 제출하는 업데이트는 {key: key} 뿐이며 다른 업데이트는 고려하지 않고 두 번째 것만 고려합니다 결국 등록 될 것입니다.

    import multiprocessing 
    
    
    def worker(key, container): 
        container['a'][key] = key 
        container[key] = 3 
    
    
    if __name__ == "__main__": 
        multiprocessing.freeze_support() 
    
        manager = multiprocessing.Manager() 
        container = manager.dict() 
        container['a'] = manager.dict() 
    
        p1 = multiprocessing.Process(target=worker, args=('x', container)) 
        p2 = multiprocessing.Process(target=worker, args=('y', container)) 
    
        p1.start() 
        p2.start() 
        p1.join() 
        p2.join() 
        print(container.copy()) 
        print(container['a'].copy()) 
    
:

  • 더 좋은 방법은 Manager.dict 중첩을 사용하는 것입니다

  • 0

    난이 a bug 생각을 사용하는 경우 출력은 동일합니다.

    문제를 우회하는 난해한 방법을 발견했습니다. 얼마나 강건한 지 확신 할 수 없습니다. 모든 의견을 환영합니다.

    import multiprocessing 
    
    def worker(key, container): 
        add = {key: key} 
        container['a'] = dict(container['a'], **add) 
        container[key] = 3 
    
    if __name__ == "__main__": 
        multiprocessing.freeze_support() 
    
        c = multiprocessing.Manager().dict() 
        c['a'] = {} 
    
        p1 = multiprocessing.Process(target=worker, args=('x',c,)) 
        p2 = multiprocessing.Process(target=worker, args=('y',c,)) 
    
        p1.start() 
        p2.start() 
        p1.join() 
        p2.join() 
        print(c.copy()) 
    

    {'y': 3, 'a': {'y': 'y', 'x': 'x'}, 'x': 3}