Сохранение глобального состояния в приложении flask

Я пытаюсь сохранить словарь кэша в моем 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"

но похоже, что они сбрасываются с каждым запросом.

как это сделать правильно?

Edit: фляга 10.1

3 ответов


основываясь на вашем вопросе, я думаю, что вы смущены определением "глобального".

в настройке колбы запаса у вас есть сервер колбы с несколькими потоками и потенциально несколькими процессами обработки запросов. Предположим, у вас есть глобальная переменная типа "itemlist = []", и вы хотите продолжать добавлять ее в каждый запрос - скажем, каждый раз, когда кто-то делает запрос POST в конечную точку. Это вполне возможно в теории и практике. Это также очень плохо идея.

проблема в том, что вы не можете легко контролировать, какие потоки и процессы "выигрывают" - список может быть в действительно шатком порядке или полностью поврежден. Итак, теперь вам нужно поговорить о замках, мьютексах и других примитивах. Это тяжело и раздражает.

вы должны сохранить сам веб-сервер как можно без гражданства. Каждый запрос должен быть полностью независимым и не иметь общего состояния на сервере. Вместо этого используйте базу данных или слой кэширования, который будет обрабатывать состояние для тебя. Это кажется более сложным, но на самом деле проще на практике. Проверьте SQLite, например; это довольно просто.

для борьбы с флягой.G ' object, это глобальный объект на согласно запросу.

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

он "очищается" между запросами и не может использоваться для совместного использования состояния между ними.


эта строка

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

поскольку вы используете ключевое слово "with", после выполнения этого цикла он вызывает __exit__ метод класса AppContext. См.этой. Таким образом, " foo " выскакивает один раз. Вот почему у вас его больше нет. Вместо этого вы можете попробовать:

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

пока вы не вызовете следующее, g.foo должен быть доступен

ctx.pop()

Я howver не уверен, хотите ли вы использовать это для кэширования.


Я сделал что-то похожее на вашу идею "модульных переменных", которую я использую в сервере колбы, который я использую для интеграции двух частей программного обеспечения, где я знаю, что у меня будет только один одновременный "пользователь" (являющийся программным обеспечением отправителя).

мой 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()

вы можете проверить это так:

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())

выходы:

0
1
2
2
3
0
0

используйте с осторожностью, поскольку я ожидаю, что это не будет вести себя на правильном многопользовательском веб-сервере окружающая среда.