When you split a Flask app into several files, importing the app object directly from one module into another very easily causes a circular import. The fix is current_app — a proxy that points to the application handling the current request — used in views, blueprints, and helpers instead of holding a reference to a specific app. It only works while an application context is active, and it fits the application factory pattern especially well.
The problem
Suppose app.py creates the application and helpers.py needs to read configuration. The direct approach looks harmless:
# helpers.pyfrom app import appdef get_upload_folder(): return app.config["UPLOAD_FOLDER"]
# app.pyfrom flask import Flaskfrom helpers import get_upload_folderapp = Flask(__name__)app.config["UPLOAD_FOLDER"] = "uploads"
The problem shows up as soon as app.py imports helpers while helpers imports app back. Python has not finished creating the app object yet when it is forced back into the half-initialized module, so you typically get ImportError: cannot import name 'app' from partially initialized module. The larger the project grows, the easier this error is to hit.
The solution
Flask provides current_app — a proxy resolved at runtime that points to the application bound to the current context. You do not need to know where the app was created; you just use it while a request or application context is active:
# helpers.pyfrom flask import current_appdef get_upload_folder(): return current_app.config["UPLOAD_FOLDER"]
# routes.pyfrom flask import Blueprint, current_appbp = Blueprint("main", __name__)@bp.route("/upload-folder")def upload_folder(): current_app.logger.info("Reading upload folder") return {"folder": get_upload_folder()}
Because helpers.py no longer imports app, the import cycle disappears, and the same helper works for several applications — for example the main app and a test app with its own configuration. current_app also gives you the config, logger, and extensions of exactly the app that is running.
Two important notes. First, do not read current_app at module level, because no context is active at that point. Read it inside a function. Second, outside a request — for example in a background thread or a standalone script — you must create the context yourself:
def send_report(app): with app.app_context(): folder = get_upload_folder() current_app.logger.info("Sending report from %s", folder)
Inside the with app.app_context(): block, current_app points to exactly the app you passed in. If you forget this step, Flask reports Working outside of application context — a sign you need to wrap the code in a context instead of going back to a direct import.
Apply it to your project
Review your helpers and services, find lines like from app import app, and replace them with current_app inside function bodies. Keep the application factory returning the app, so blueprints and helpers no longer depend on one specific global variable. In tests, use the test client or wrap code in app.app_context(). After this step, splitting off another blueprint or renaming a module is far less likely to break imports.
Related posts
- Flask: Use the Application Factory (create_app) for Apps That Are Easy to Test and Extend
- Flask: Organize Routes Cleanly with Blueprints as Your Project Grows
- Flask: Stop Hardcoding URLs — Use url_for So Route Changes Never Break Links
Frequently asked questions
How is current_app different from a normal app object?
current_app is a proxy: it only points to the application that is active while an application context exists. That is why the same code runs against different apps without importing a specific app.
When do you get “Working outside of application context”?
When you access current_app outside a request and outside an app.app_context() block — for example in a background thread, a standalone script, or at module level during import. The fix is to wrap that code in with app.app_context():.
Should you use current_app in every helper?
Yes, if the helper needs to read config, write logs, or access an app extension. If a helper only processes plain data and needs no app, keep it independent so it stays easy to test and reuse.
Does current_app work with the application factory?
Yes, and that is where it shines most. The factory can create several apps with different configurations, while blueprints and helpers using current_app always see the app that is actually running.
💬 Have you tried this in your own project? If you hit an error or know a cleaner way, leave a comment below — I read them all and will fold the best ideas into the post.
Sources
- Flask — Application Context: https://flask.palletsprojects.com/en/stable/appcontext/
- Flask API — current_app: https://flask.palletsprojects.com/en/stable/api/#flask.current_app
