I am working on a Flask application with a MongoDB database.
I am using that database for my core application data as well as for Flask-Dance token storage (https://flask-dance.readthedocs.io/en/latest/storages.html). The code for the custom storage backend is in token_storages.py
, below.
Everything is working perfectly in the Flask development server, but when I try running my prod server via uWSGI I get this error:
UserWarning: MongoClient opened before f
ork. Create MongoClient only after forking. See PyMongo's documentation for details: https://pymongo.readthedocs.io/en/stable/faq.html#is-
pymongo-fork-safeUserWarning: MongoClient opened before f
ork. Create MongoClient only after forking. See PyMongo's documentation for details: https://pymongo.readthedocs.io/en/stable/faq.html#is-
pymongo-fork-safe
All the research I have seen refers to setting connect=False
when instantiating PyMongo, but this is having no effect. Per the docs, this setting should be default regardless (https://flask-pymongo.readthedocs.io/en/latest/).
The error doesn't actually show me on what line things are going wrong -- any guidance on how to find what it PyMongo regards as errant would be much appreciated.
All the database calls that I can find are made within the Flask routes, which I believe should work fine (see the example from storyboard_routes.py
below.
I believe the below code should be enough to provide details on the app construction but please let me know if anything else should be included.
Finally I did find that setting lazy-apps = true
in my uWSGI settings does work around this issue (in wsgi.ini
) but I would rather solve the root issue if possible.
Thanks in advance!
This was suggested, but at least today it is inaccurate as connect=true is not the current default. I tried it nevertheless without success. MongoClient opened before fork. Create MongoClient only Flask
Related Versions
Python 3.8.10 pymongo 3.12.0 Flask-PyMongo 2.3.0 Flask 2.0.1 Flask-Dance 5.0.0
my_app/init.py
from flask import Flask
from flask_session import Session # https://pythonhosted.org/Flask-Session
from . import app_config
from .util import misc
from .routes import graph_auth_routes
from .routes import google_auth_routes
from .routes import storyboard_routes
from .db import init_db
def create_app():
app = Flask(__name__)
app.config.from_object(app_config)
azure_oauth = misc.create_azure_dance_blueprint(app)
google_oauth = misc.create_google_dance_blueprint(app)
app.config['MONGO_CONNECT'] = False # This has no effect since already the default
init_db(app)
Session(app)
app.register_blueprint(graph_auth_routes.bp)
app.register_blueprint(google_auth_routes.bp)
app.register_blueprint(storyboard_routes.bp)
return app
app=create_app()
my_app/db.py
from flask_pymongo import PyMongo
mongo = PyMongo()
def init_db(app):
print("Initializing DB")
mongo.init_app(app)
return app
my_app/util/token_storages.py
from flask import session
from flask_dance.consumer.storage import BaseStorage
from ..db import mongo
class MongoStorage(BaseStorage):
def __init__(self, oauth_provider):
self.oauth_provider = oauth_provider
def get(self, blueprint):
print("getting token")
try:
token = mongo.db["tokens"].find_one(
{
"contact_id": session["contact_id"],
"oauth_provider": self.oauth_provider,
}
)["oauth"]["token"]
return token
except:
print("can't find token for %s" % self.oauth_provider)
return None
def set(self, blueprint, token):
print("setting token")
query = mongo.db["tokens"].update_one(
{
"contact_id": session["contact_id"],
"oauth_provider": self.oauth_provider,
},
{"$set": {"oauth.token": token, "oauth_provider": self.oauth_provider}},
upsert=True,
)
def delete(self, blueprint):
print("deleting token")
mongo.db["tokens"].delete_one(
{
"contact_id": session["contact_id"],
"oauth_provider": self.oauth_provider,
}
)
return None
my_pp/routes/storyboard_routes.py
@bp.route("/page2_365")
@misc.default_error_handler
def page2_365():
# Update if Google integration was performed
if request.args.get("gc_integration"):
filter = {"_id": session["contact_id"]}
new_value = {
"$set": {"gc_integration": misc.str2bool(request.args["gc_integration"])}
}
mongo.db["contacts"].update_one(filter, new_value)
wsgi.ini
[uwsgi]
module = lead_wizard:app
master = true
processes = 5
workers=1
socket = /tmp/lead_wizard.sock
chmod-socket = 666
vacuum = true
die-on-term = true