1

I have a flask app that I wanted to add a cache to for API calls, so I wrote a simple caching class that doesn't know anything about flask, just about the cache data, and managing it. It lives in a separate file that starts:

import logging
import time

logger = logging.getLogger(__name__)


class CacheCollection:

and uses logger.debug("xxx") in various places to let you know what's going on.

That all works fine in standalone test code.

HOWEVER, I would like to create this cache in my flask app, and ideally seed it with data when the application starts up. Since Flask hasn't got a "on startup" event like Django does, I am adding this in the init_bp() method of my Blueprint. It needs to be after Flask's config is loaded, since the endpoint and key for the API I'm caching is in that config.

When I do that, I get a warning on the first call to the logger in the cache class:

RuntimeError: Working outside of application context.

which is true I guess, but I don't see why it's relevant. Does Flask mess with the logging config enough to break other modules' logging? Having to create a dependency on current_app.logger in this other module seems perverse (and I don't think it will help).

How should I be creating these objects outside of a request? I don't want to use before_first_request, since it might take a while to run. Other similar questions on SO seem to be for work unrelated to the application itself, running in another thread or something similar.

0

1 Answer 1

1

Indeed, Flask apps do not have "on startup" method. But you can easily bypass this problem by using a Application Factory pattern as described here: Application Factories. That allows you to execute code after the app is created and before it runs.


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(). (Manually Push a Context)

Flask provides an easy solution:

def create_app():
    app = Flask(__name__)

    with app.app_context():
        init_bp()

    return app

Another solution, it is to use the other pattern to initialize extensions (commonly use). You will have access to the app object from your init_bp function.

init_bp(app)
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, I will check into this to avoid my current method (I do already use an application factory), but the other question remains - why does Flask even get involved in my non-flask code? I ran it with the debugger and didn't see any references to Flask in the root logger, for example. I'm not using current_app.logger, just logging.getLogger(__name__)
Wihtout any reproductible code, it is hard to say. You are doing something that needs the app context, try to find what needs the context, or push it manually.
I made a minimal app that behaves the same, and in the process realised that actually I'm using json_logging, and it's that that is the issue - it was trying to get context information from the current request (which is there isn't one) to create correlation IDs. Updating to latest json_logging resolved it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.