Accessing multiprocessing manager dict from webserver

169 Views Asked by At

I've been trying to share a multiprocessing manager dict with a web server so far with little success. The dict contains information but somehow it is not propagated to the running web server. The goal ultimately is to be able to intermittently poll data from the shared dictionary while the processes are running.

The output from the main process is [('foo', 0), ('bar', '1')] But when I make a get request I get an empty dict and a key error respectively.

from multiprocessing import Process, Manager
from pprint import pprint

from sanic import Sanic, json

app = Sanic(name='status_app')

manager_dict = {}
process_dict = {}


@app.get('/status')
def status(request):
    return json(manager_dict)


@app.get('/status/<pair:str>/')
def status_ext(request, pair):
    return json({pair: manager_dict[pair]})


def run_async_server():
    app.run(host="0.0.0.0", port=8000)
    return True


def build_process_dict():
    global process_dict
    process_dict = {
        'server': Process(target=run_async_server)
    }
    for _, p in process_dict.items():
        p.start()

    for _, p in process_dict.items():
        p.join()


def build_manager_dict():
    global manager_dict
    manager_dict = Manager().dict()
    manager_dict['foo'] = 0
    manager_dict['bar'] = '1'


if __name__ == '__main__':
    build_manager_dict()
    pprint(manager_dict.items())
    build_process_dict()
1

There are 1 best solutions below

0
Dr Acme Isme On

I actually found a way to inject the manager into the app's context. This solved the problem for me. I'd be interested to know why the above code worked for others.

from multiprocessing import Process, Manager
from pprint import pprint

from sanic import Sanic, json

app = Sanic(name='status_app')

@app.get('/status')
async def status(request):
    return json(dict(app.ctx.manager_dict))


@app.get('/status/<pair:str>/')
async def status_ext(request, pair):
    return json({pair: app.ctx.manager_dict[pair]})


def run_async_server(manager_dict):
    app.ctx.manager_dict = manager_dict
    app.run(host="0.0.0.0", port=8000)
    return True


def build_manager_dict():
    global manager_dict
    manager_dict = Manager().dict()
    manager_dict['foo'] = 0
    manager_dict['bar'] = '1'


def build_process_dict():
    global process_dict
    process_dict = {
        'server': Process(target=run_async_server, args=[manager_dict]),
    }
    for _, p in process_dict.items():
        p.start()

    for _, p in process_dict.items():
        p.join()


if __name__ == '__main__':
    build_manager_dict()
    pprint(manager_dict.items())
    build_process_dict()