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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19277280/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 13:19:01  来源:igfitidea点击:

Preserving global state in a flask application

pythonflaskglobalstate

提问by Profpatsch

I am trying to save a cache dictionary in my flaskapplication.

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

As far as I understand it, the Application Context, in particular the flask.g objectshould be used for this.

据我了解,应为此使用Application Context,特别是flask.g 对象

Setup:

设置:

import flask as f

app = f.Flask(__name__)

Now if I do:

现在,如果我这样做:

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

It prints bar.

它打印bar.

Continuing with the following:

继续以下内容:

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

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

I don't understand it and the docs are not helping at all. If I read them correctly the state should have been preserved.

我不明白,文档根本没有帮助。如果我正确阅读它们,状态应该被保留。

Another ideaI had was to simply use module-wide variables:

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

cache = {}

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

But it seems like these get reset with every request.

但似乎每次请求都会重置这些。

How to do this correctly?

如何正确地做到这一点?

Edit:Flask 10.1

编辑:烧瓶 10.1

采纳答案by mallyvai

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.

在库存 Flask 设置中,您有一个 Flask 服务器,该服务器具有多个线程和潜在的多个处理请求的进程。假设您有一个像“itemlist = []”这样的常用全局变量,并且您想在每个请求中不断添加它 - 例如,每次有人向端点发出 POST 请求时。这在理论上和实践上都是完全可能的。这也是一个非常糟糕的主意。

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.

您应该使网络服务器本身尽可能无状态。每个请求应该是完全独立的,并且不共享服务器中的任何状态。相反,使用将为您处理状态的数据库或缓存层。这看起来更复杂,但实际上更简单。以 SQLite 为例;这很简单。

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

为了解决“flask.g”对象,它是基于每个请求的全局对象。

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

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

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

它在请求之间被“清除干净”,不能用于在它们之间共享状态。

回答by codegeek

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:

由于您使用了“with”关键字,因此一旦执行此循环,它就会调用__exit__AppContext 类的方法。看到这个。因此,一旦完成,'foo' 就会弹出。这就是为什么你没有它再次可用。您可以尝试:

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

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

在调用以下命令之前,g.foo 应该可用

ctx.pop()

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

但是,我不确定您是否想将其用于缓存。

回答by Johan Gov

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:

我的 app.py 看起来像这样:

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.

请谨慎使用,因为我希望这不会在适当的多用户 Web 服务器环境中运行。