2

Problem: Flask app.teardown_appcontext is not being called when DEBUG is false. Flask's app.teardown_request works just fine.

Background: This problem was first discovered because of the error (2013, 'lost connection to mysql server during query') which was only happening when DEBUG = False

After looking into this further, I realized that this was because the session was not being removed properly in flask_sqlalchemy.

def create_app(config_obj):
    app = Flask(__name__)
    env = Environments(app)
    env.from_object(config_obj)

    # init extensions
    SetupLogs(app)
    db.init_app(app)
    api.init_app(app)
    CORS(app)

    # This gets called after each request
    @app.teardown_request
    def teardown_request(response_or_exc):
        db.session.remove()

    # This never gets called after requests only when DEBUG = False!
    @app.teardown_appcontext
    def teardown_appcontext(response_or_exc):
        db.session.remove()

    return app

app = create_app('config')
manager = Manager(app)
migrate = Migrate(app, db)
...
amueller
  • 41
  • 1
  • 4
  • I am not very sure and that is why I am not writing an answer but may be reading this - http://flask.pocoo.org/docs/0.12/appcontext/#context-usage will help you. Just to quote - `"Generally there would be a get_X() function that creates resource X if it does not exist yet and otherwise returns the same resource, and a teardown_X() function that is registered as teardown handler."` – SRC Feb 20 '18 at 19:29
  • @SRC flask-sqlalchemy creates the scoped session at the start of the request, and is suppose to remove the session after each request. See details in [the road to enlightenment](http://flask-sqlalchemy.pocoo.org/2.3/quickstart/#road-to-enlightenment). [Removing](https://github.com/zzzeek/sqlalchemy/blob/master/lib/sqlalchemy/orm/scoping.py#L76) does a little more than just closing the session – amueller Feb 20 '18 at 20:02

1 Answers1

2

I finally found the problem and it was actually a side effect of using Flask-Script with Flask-SqlAlchemy.

If SQLAlchemy is instantiated with init_app, then app.app_context().push() must be used if performing DB operations outside of the scoped session(made in the request). More Details But if an app context is pushed, then it must be closed manually otherwise it will never be torn down and therefore never trigger the teardown_appcontext.

Flask-Script runs commands inside a flask test context which i believe kept the app context alive.

amueller
  • 41
  • 1
  • 4