如何在Flask中存储自定义变量

3 投票
2 回答
5286 浏览
提问于 2025-04-18 00:20

我需要定义一些自己的变量,这些变量在服务器运行时会被保存。我尝试使用 flask.g,但是出现了错误:

AttributeError: '_AppCtxGlobals' object has no attribute 'x'

这是我的代码:

from flask import *
app=Flask(__name__)
@app.route('/')
def opa():
    #Added this to define variable
    try:
        g.x
    except NameError:
        g.x=None
    #Added this to add value to variable
    if g.x is None:
        g.x='Already defined'
        return 'x is now defined'
    else:
        return g.x
if __name__ == "__main__":
    app.run(host='0.0.0.0',port=8081,debug=True)

2 个回答

3

访问一个属性时会抛出 AttributeError 错误,而不是 NameError 错误:

try:
    g.x
except AttributeError:
    g.x = None

在这里,使用 in 来测试是否存在 会更好:

if 'x' not in g:
    g.x = 'Already defined'
    return 'x is now defined'
else:
    return g.x

我给你链接的文档中还提到可以使用 g.get()getattr() 作为替代方案:

x = g.get('x', None)
# x = getattr(g, 'x', None)
if x is None:
    g.x = 'Already defined'
    return 'x is now defined'
else:
    return x

需要注意的是,g 这个全局上下文是 与请求相关联的;你不能在它上面存储跨请求的全局变量。g 主要用于在你的应用的不同函数和模板之间共享数据,而不是在不同请求之间。

如果需要跨请求的全局变量,就要使用真正的全局变量(最好通过 app.before_first_request() 钩子 设置,或者使用某种缓存方式,比如 Flask-Cache)。

设置一个全应用的全局变量:

x = None

@app.before_first_request
def set_x():
    global x
    x = 'x is now defined'

通过使用 before_first_request,你可以确保 x 只在应用启动时设置一次,即使你使用的是处理请求的多进程服务器。

或者使用缓存:

from flask.ext.cache import Cache

cache = Cache(app)

@cache.memoize(timeout=3600)  # cache for one hour
def produce_x():
    return 'x is now defined'

然后在需要定义 x 时使用 produce_x();这在计算 x 的代价很高,但又必须不时重新计算时非常有用。

1

更简单的方法可以这样做:

x = getattr(flask.g, 'x', None)
if x is None:
    g.x = 'Already defined'
    return 'x is now defined'
else:
    return g.x

另外,你可以看到你的代码出现了 AttributeError 错误。所以如果你想保留你的尝试/捕获代码,那么你需要特别捕获 AttributeError,而不是 TypeError

try:
    g.x
except AttributeError:
    g.x=None

if g.x is None:
    g.x='Already defined'
    return 'x is now defined'
else:
    return g.x

撰写回答