在烧瓶应用程序中保持全局状态

我试图在我的 flask应用程序中保存一个缓存字典。

据我所知,应该使用 应用环境,特别是 对象

设置:

import flask as f


app = f.Flask(__name__)

如果我这么做了:

with app.app_context():
f.g.foo = "bar"
print f.g.foo

它可以打印 bar

继续下面的内容:

with app.app_context():
print f.g.foo


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

我不明白,医生也帮不上忙。如果我没有看错的话,这个状态应该是被保留下来的。

我的另一个想法是简单地使用模块范围的变量:

cache = {}


def some_function():
cache['foo'] = "bar"

但似乎每个请求都会重置。

如何正确地做到这一点?

编辑: Flask 10.1

99397 次浏览

This line

with app.app_context():
f.g.foo = "bar"

Since you are using the "with" keyword, once this loop is executed, it calls the __exit__ method of the AppContext class. See this. So the 'foo' is popped out once done. Thats why you don't have it available again. You can instead try:

ctx = app.app_context()
f.g.foo = 'bar'
ctx.push()

Until you call the following, g.foo should be available

ctx.pop()

I am howver not sure if you want to use this for the purpose of caching.

Based on your question, I think you're confused about the definition of "global".

In a stock Flask setup, you have a Flask server with multiple threads and potentially multiple processes handling requests. Suppose you had a stock global variable like "itemlist = []", and you wanted to keep adding to it in every request - say, every time someone made a POST request to an endpoint. This is totally possible in theory and practice. It's also a really bad idea.

The problem is that you can't easily control which threads and processes "win" - the list could up in a really wonky order, or get corrupted entirely. So now you need to talk about locks, mutexs, and other primitives. This is hard and annoying.

You should keep the webserver itself as stateless as possible. Each request should be totally independent and not share any state in the server. Instead, use a database or caching layer which will handle the state for you. This seems more complicated but is actually simpler in practice. Check out SQLite for example ; it's pretty simple.

To address the 'flask.g' object, that is a global object on a per request basis.

http://flask.pocoo.org/docs/api/#flask.g

It's "wiped clean" between requests and cannot be used to share state between them.

I've done something similar to your "module-wide variables" idea that I use in a flask server that I use to integrate two pieces of software where I know I will only ever have one simultaneous "user" (being the sender software).

My app.py looks like this:

from flask import Flask
from flask.json import jsonify
app = Flask(__name__)


cache = {}


@app.route("/create")
def create():
cache['foo'] = 0
return jsonify(cache['foo'])


@app.route("/increment")
def increment():
cache['foo'] = cache['foo'] + 1
return jsonify(cache['foo'])


@app.route("/read")
def read():
return jsonify(cache['foo'])


if __name__ == '__main__':
app.run()

You can test it like this:

import requests


print(requests.get('http://127.0.0.1:5000/create').json())
print(requests.get('http://127.0.0.1:5000/increment').json())
print(requests.get('http://127.0.0.1:5000/increment').json())
print(requests.get('http://127.0.0.1:5000/read').json())
print(requests.get('http://127.0.0.1:5000/increment').json())
print(requests.get('http://127.0.0.1:5000/create').json())
print(requests.get('http://127.0.0.1:5000/read').json())

Outputs:

0
1
2
2
3
0
0

Use with caution as I expect this to not behave in a proper multi user web server environment.