Подтвердить что ты не робот

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

Я пытаюсь сохранить словарь кеша в моем приложении flask.

Насколько я понимаю, Контекст приложения, в частности, объект flask.g должен для этого.

Настройка:

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"

но кажется, что они получают reset с каждым запросом.

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

Изменить: Колба 10.1

4b9b3361

Ответ 1

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

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

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

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

Чтобы обратиться к объекту 'flask.g', это глобальный объект для каждого запроса.

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

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

Ответ 2

Эта строка

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

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

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

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

ctx.pop()

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

Ответ 3

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

My 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

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