"Working outside of application context" is the most common Flask error, and contexts explain it.
Flask avoids passing the app and request into every function by using contexts. During a request, Flask pushes:
- the application context, which makes
current_appandgavailable - the request context, which makes
requestandsessionavailable
Both are popped when the response is sent. Outside a request, for example in a script, a CLI command, a background thread or the Python shell, there is no context, and touching current_app raises RuntimeError: Working outside of application context. Push one yourself:
with app.app_context():
init_db()CLI commands registered with @app.cli.command() already run inside an app context. For code that needs request or url_for with a host, use app.test_request_context("/path").
`g` is a namespace object for data scoped to one app context, which in practice means one request. It is the right place for per-request resources: the current user loaded from the session, or a database connection opened lazily on first use.
def get_db():
if "db" not in g:
g.db = connect()
return g.dbClean up with @app.teardown_appcontext, which runs when the context ends, even after an exception.
Don't store anything on g expecting it to survive to the next request; it doesn't. Use the session or a database for that. And don't stash request or current_app in a global or pass them to another thread: they are proxies that only work while their context is active.
Example
import sqlite3
from flask import Flask, current_app, g
app = Flask(__name__)
app.config["DATABASE"] = ":memory:"
def get_db():
if "db" not in g: # open lazily, once per context
g.db = sqlite3.connect(current_app.config["DATABASE"])
return g.db
@app.teardown_appcontext
def close_db(exc):
db = g.pop("db", None)
if db is not None:
db.close()
@app.get("/")
def index():
get_db(); get_db() # second call reuses the connection
return {"sum": get_db().execute("select 1 + 1").fetchone()[0]}
print(app.test_client().get("/").json) # {'sum': 2}
try:
current_app.name
except RuntimeError as e:
print(str(e).splitlines()[0]) # Working outside of application context.Remember
- During a request, current_app/g and request/session are available
- Outside a request, push one with app.app_context() or test_request_context()
- g holds per-request resources; clean up in teardown_appcontext
Watch out for
- Expecting values on g to persist across requests.