bigywater.tech
Flask · 3

Flask Application Context

为什么在视图函数之外用 current_app 会报错?g 到底活多久?一个请求里应用上下文什么时候出现、什么时候消失?这篇逐个实测。

9
一次请求里被观察到的事件数(从 appcontext_pushed 到 appcontext_popped)
1
三次请求里 g.hits 每次的值
3
嵌套演示里 current_app 经历的名字个数(outer、inner、outer)

没有上下文时

实测 · 本机执行输出
  current_app.name   → RuntimeError: Working outside of application context. This typically means that you attempted to use functionality that needed the current application. To solve this, set up an application context with app.app_context(). See the documentation for more information.
  g.x                → RuntimeError: Working outside of application context. This typically means that you attempted to use functionality that needed the current application. To solve this, set up an application context with app.app_context(). See the documentation for more information.
  url_for            → RuntimeError: Working outside of application context. This typically means that you attempted to use functionality that needed the current application. To solve this, set up an application context with app.app_context(). See the documentation for more information.
  has_app_context(): False | has_request_context(): False

上一篇:app.run() 的启动过程;下一篇:Flask Request Context。

app_context()

实测 · 本机执行输出
  源码:
      1 | app = Flask("demo")
      2 | with app.app_context():
      3 |     print(current_app.name, has_app_context())
      4 |     print(current_app is app, current_app._get_current_object() is app, type(current_app).__name__)
      5 | print(has_app_context())
  demo True
  False True LocalProxy
  False

g 的生命周期

实测 · 本机执行输出
  g.hits=1 模块变量=1 g 的 id=19280
  g.hits=1 模块变量=2 g 的 id=20560
  g.hits=1 模块变量=3 g 的 id=19200

回调与信号顺序

实测 · 本机执行输出
  appcontext_pushed → request_started → before_request → 视图函数 → after_request → request_finished → teardown_request(exc=None) → teardown_appcontext(exc=None) → appcontext_popped

请求上下文与应用上下文

实测 · 本机执行输出
  GET /boom → 500; ['teardown_appcontext 收到:ValueError']
  test_request_context 内:has_app_context = True , has_request_context = True , request.path = /x
  app_context 内:has_app_context = True , has_request_context = False
  在应用上下文里访问 request.path → Working outside of request context. This typically means that you attempted to use functionality that needed an active HTTP request. Consult the documentation on testing for information about how to a

嵌套

实测 · 本机执行输出
   ['outer', 'inner', 'outer']

命令行

实测 · 本机执行输出
  flask --app cliapp hello → has_app_context=True current_app.name=cliapp
    test_cli_runner: has_app_context=True current_app.name=cliapp
    手动调用函数(没有 flask 命令): RuntimeError There is no active click context.

分步演示

应用上下文
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Python 3.14.7 / Flask 3.1.3 / Werkzeug 3.1.9 / Jinja2 3.1.6 / SQLAlchemy 2.1.1 / gunicorn 26.2.0(都装在自己的虚拟环境里);大多数实验用 Flask 的 test_client(直接调用 WSGI 应用,不经过网络),需要真实 HTTP 时另起 gunicorn 或开发服务器(端口 9600 以上,本机 127.0.0.1);计时用 time.perf_counter,数字每次运行会有小幅抖动
    • 没有验证:异步视图与 greenlet 下的上下文行为(见第 142 篇)、后台线程里的用法(见第 146 篇)、teardown_appcontext 回调的注册顺序与异常处理、Flask 其它版本里的上下文栈实现差异
    京ICP备2026067502号-1京公网安备11010502063487号