flask 中 g 对象仅在请求上下文中有效,生命周期始于 @app.before_request、终于响应发出,不可跨请求共享;模板中无法直接访问 g,需用 add_template_global 注册 jinja2 全局变量;跨请求状态应使用 session 或 redis,避免 g 名冲突需加前缀。

Flask 里没有真正意义上的“全局变量”,所有看似全局的变量都绑定在上下文里;直接用模块级变量(global)在多线程或多进程部署下必然出错。
g 对象只在请求上下文中有效,离开 request 就会报 RuntimeError: Working outside of application context.
这是最常踩的坑:有人在 app.run() 外、或在后台线程、或在异步任务里直接访问 g.user,结果崩得干脆利落。
-
g的生命周期严格对应单个请求 —— 从@app.before_request开始,到视图函数返回、响应发出后自动清空 - 它不是跨请求共享的,两次 HTTP 请求的
g完全隔离,哪怕同一个用户登录两次,第二次的g也是全新对象 - 不能在
before_first_request或应用启动时初始化g,因为那时还没有请求上下文 - 正确写法是:在
@app.before_request中设置,比如g.current_user = get_current_user_from_token(request.headers)
想让变量在模板里全局可用?用 add_template_global,别往 g 里塞
很多人误以为把数据塞进 g 就能在 Jinja2 模板里直接写 {{ g.site_name }} —— 不行。模板渲染时 g 已不可见,除非你手动传进去。
Miller (mlr) 是一个命令行工具,用于查询、整形和重新格式化名称索引数据,如 CSV、TSV、JSON 和 JSON Lines。它将 awk、sed、cut、join 和 sort 的功能整合到一个专为结构化数据处理而构建的单一工具中。
- 要让函数或值在所有模板中都能调用,必须注册为 Jinja2 全局变量:
app.add_template_global(lambda: 'MySite', 'site_name') - 也可以注册函数:
app.add_template_global(current_time, 'now'),模板里就能写{{ now() }} - 注意:这些是 Jinja2 层面的“全局”,和
g无关,也不受请求上下文保护;它们在应用启动时就确定,不会随请求变化
需要跨请求存状态?别硬扛,换 session 或外部存储
有用户试图用 g 存“用户已读消息数”,然后在多个接口间复用 —— 这注定失败。因为下一次请求,g 彻底重置。
-
session是唯一被设计用于跨请求保存用户级数据的 Flask 内置机制(底层加密签名 Cookie) - 如果数据量大或需共享给其他服务,该上 Redis:
redis_client.setex(f"user:{uid}:counter", 3600, count) - 数据库也行,但要注意避免高频读写拖慢接口;
g绝对不适合做这种缓存层
真正容易被忽略的一点:g 的 key 名冲突风险很高。扩展(如 Flask-SQLAlchemy)也可能往 g 写东西,所以别用太泛的名,比如 g.data 或 g.config —— 推荐加前缀,如 g.myapp_user_profile。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










