Search code examples
pythonflaskuwsgi

How to initialize MongoClient in a multiprocess Flask application?


I have a Flask application which I'm running with uWSGI. The application initializes a MongoClient(). When running uWSGI with multiple workers I'm getting the MongoClient opened before fork warning.

I saw that one way to overcome this problem is to initializethe MongoClient inside an init method decorated with uWSGI's @postfork

The problem is that after the change my tests fails because pytest can't find uwsgi

#15 1.880 usr/local/lib/python3.9/site-packages/uwsgidecorators.py:10: in <module>
#15 1.880     import uwsgi
#15 1.880 E   ModuleNotFoundError: No module named 'uwsgi'

Questions:

  • Is there any other easy way to initialize a MongoClient for each process?
  • If not, how can I test my app.py?

Solution

  • Is there any other easy way to initialize a MongoClient for each process?

    Wherever you use that client, use a function to acquire it, like below.

    The function has guards to ensure each process gets their own client.

    _mongo_client = None
    _mongo_client_pid = None
    
    
    def get_mongoclient():
        global _mongo_client, _mongo_client_pid
        if os.getpid() != _mongo_client_pid:
            _mongo_client = MongoClient(...)
            _mongo_client_pid = os.getpid()
        return _mongo_client
    

    If not, how can I test my app.py?

    You could use a guard like

    try:
        from uwsgi import postfork
    except ImportError:
        postfork = lambda f: f  # no-op decorator
    

    to make your app work with and without uwsgi. The @postfork-marked code won't be called outside uwsgi.