0

Here is the project Structure.

|-- a_api/
|    |- a1.py
|
|-- b_api/
|    |-b1.py
|
|-- c_api/
|    |-c1.py
|    |-c2.py
|
|-- utils/
|    |-db.py
|
|-- main.py

db.py connects to mongo and stores connection in g from flask.


from flask import g
from pymongo import MongoClient

mongo_db = 'mongo_db'

def get_mongo_db():
    """Function will create a connection to mongo db for the current Request

    Returns:
        mongo_db: THe connection to Mongo Db
    """
    if mongo_db not in g:
        print('New Connection Created for mongo db')
        mongo_client = MongoClient('the_url')

        # Store the Client
        g.mongo_db = mongo_client
    else:
        print('Old Connection reused for mongo db')
    # Return The db
    return g.mongo_db['db_name']
  1. main.py calls two functions a1.py and b1.py
  2. for a1: it interacts directly with the db.py file and updates data, this happens without any error and task is completed successfully.
  3. for b1: it first calls c1 in a separate process, which used db.py and updates data - but in this case an error is thrown set up an application context with app.app_context()

How do I pass the application context to db.py when it is called from c1, which is called from b1?

How Do I create a single connection point to mongodb and use it across all requests or process in flask?

Traceback (most recent call last):
  File "C:\Users\kunda\AppData\Local\Programs\Python\Python310\lib\multiprocessing\process.py", line 315, in _bootstrap
    self.run()
  File "C:\Users\kunda\AppData\Local\Programs\Python\Python310\lib\multiprocessing\process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "W:\xx\offers_api\offer_ops.py", line 60, in update_offer
    response = aser(id=id, d=d)
  File "W:\xx\offers_api\offer_ops.py", line 86, in aser
    x = get_mongo_db()
  File "W:\xx\utils\db.py", line 13, in get_mongo_db
    if mongo_db not in g:
  File "C:\Users\kunda\AppData\Local\Programs\Python\Python310\lib\site-packages\werkzeug\local.py", line 278, in __get__
    obj = instance._get_current_object()
  File "C:\Users\kunda\AppData\Local\Programs\Python\Python310\lib\site-packages\werkzeug\local.py", line 407, in _get_current_object
    return self.__local()  # type: ignore
  File "C:\Users\kunda\AppData\Local\Programs\Python\Python310\lib\site-packages\flask\globals.py", line 40, in _lookup_app_object
    raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.

This typically means that you attempted to use functionality that needed
to interface with the current application object in some way. To solve
this, set up an application context with app.app_context().  See the
documentation for more information.
Kundan
  • 590
  • 9
  • 21
  • I think it has nothing to do with `application context `, it's a problem with the `db.py` coding, are you considering using connection pooling? – 山河以无恙 Nov 10 '22 at 10:46
  • it think it is problem with `application context`. It has problem with `... in g` which needs `application context`. And this may need to create `app = flask(__name__)` - but you run it in separated process and it has no access to original `app`. For separated process I would create `mongo_client = MongoClient('the_url')` without checking `g`. and without `g.mongo_db = ...` – furas Nov 10 '22 at 12:13
  • Is it possible that I create a single connection to mongo db when api is initialized, and then for all api request that single connection point is used? – Kundan Nov 12 '22 at 19:31
  • I recommend one of Flask extensions, such as [Flask-PyMongo](https://flask-pymongo.readthedocs.io/en/latest/). – relent95 Nov 14 '22 at 08:57
  • [This](https://stackoverflow.com/questions/60216421/runtimeerror-working-outside-of-application-context-with-app-app-context-not) might help? – JDODER Nov 14 '22 at 09:12
  • I found out one more post related to this, trying this one out then will try above two. https://stackoverflow.com/questions/28423069/store-large-data-or-a-service-connection-per-flask-session – Kundan Nov 14 '22 at 09:25

1 Answers1

1

Try something like this:

from flask import g
from pymongo import MongoClient

# import main flask app
from X import app

mongo_db = 'mongo_db'

def get_mongo_db():
    """Function will create a connection to mongo db for the current Request

    Returns:
        mongo_db: THe connection to Mongo Db
    """
    # if circular dependency error try importing app here
    from X import app
    with app.app_context():
        if mongo_db not in g:
            print('New Connection Created for mongo db')
            mongo_client = MongoClient('the_url')

            # Store the Client
            g.mongo_db = mongo_client
        else:
            print('Old Connection reused for mongo db')
        # Return The db
        return g.mongo_db['db_name']
Adrian Kurzeja
  • 797
  • 1
  • 11
  • 27
  • getting circular import error when implementing this. – Kundan Nov 22 '22 at 12:09
  • Edited my answer, try this out. Move import to function body and remove it from top of the file. Sometimes flask have big import dependency problems because of how it is built and how it needs to be used later, especially in larger and complex projects. – Adrian Kurzeja Nov 22 '22 at 13:23