pythondictionarymultiprocessingpython-multiprocessingmultiprocessing-manager

Unable to update nested dictionary value in multiprocessing's manager.dict()


I am trying to update a key in a nested dictionary of multiprocessing module's manager.dict() but not able to do so. It doesn't update the value and doesn't throw any error too.

Code:

import time
import random
from multiprocessing import Pool, Manager

def spammer_task(d, token, repeat):
    success = 0
    fail = 0
    while success+fail<repeat:
        time.sleep(random.random()*2.0)
        if (random.random()*100)>98.0:
            fail+=1
        else:
            success+=1
        d[token] = {
            'status': 'ongoing',
            'fail': fail,
            'success': success,
            'repeat': repeat
        }
    print d[token]['status']
    d[token]['status'] = 'complete'
    return

p = Pool()
m = Manager()
d = m.dict()

p.apply_async(spammer_task (d, 'abc', 5))
print d

Output:

ongoing

{'abc': {'status': 'ongoing', 'fail': 0, 'repeat': 5, 'success': 5}}

My expectations are that as soon as while loop ends, it should make d['abc']['status'] = complete. But on final print it prints its status as 'ongoing' only.


Solution

  • not sure why, but the Manager DictProxy object can't seem to handle mutating a nested part. this code works:

    import time
    import random
    from multiprocessing import Pool, Manager
    
    def spammer_task(d, token, repeat):
        success = 0
        fail = 0
        while success+fail<repeat:
            time.sleep(random.random()*2.0)
            if (random.random()*100)>98.0:
                fail+=1
            else:
                success+=1
            d[token] = {
                'status': 'ongoing',
                'fail': fail,
                'success': success,
                'repeat': repeat,
            }
        print d[token]['status']
        foo = d[token]
        foo['status'] = 'complete'
        d[token] = foo
        return
    
    p = Pool()
    m = Manager()
    d = m.dict()
    
    p.apply_async(spammer_task(d, 'abc', 5))
    print d