web-dev-qa-db-ja.com

flaskアプリケーションでのグローバル状態の保持

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"

しかし、これらはすべてのリクエストでリセットされるようです。

これを正しく行う方法は?

編集:Flask 10.1

55
Profpatsch

あなたの質問に基づいて、私はあなたが「グローバル」の定義について混乱していると思います。

在庫Flaskセットアップでは、複数のスレッドと潜在的に複数のプロセスがリクエストを処理するFlaskサーバーがあります。 "itemlist =のような在庫グローバル変数があったとします。 [] "、そしてあなたはすべてのリクエストでそれを追加し続けたい-例えば誰かがエンドポイントにPOSTリクエストを行ったたびに。これは理論と実践で完全に可能です。本当に悪い考え。

問題は、どのスレッドとプロセスが「勝つ」かを簡単に制御できないことです。リストが非常に不安定な順序で増えたり、完全に破損したりする可能性があります。そこで、ロック、ミューテックス、その他のプリミティブについて説明する必要があります。これは難しくて面倒です。

Webサーバー自体は可能な限りステートレスに保つ必要があります。各リクエストは完全に独立している必要があり、サーバー内の状態を共有しないでください。代わりに、状態を処理するデータベースまたはキャッシュレイヤーを使用します。これはもっと複雑に思えますが、実際には実際には簡単です。たとえば、SQLiteを確認してください。とても簡単です。

「flask.g」オブジェクトに対処するには、それはリクエストごとにグローバルオブジェクトです

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

リクエスト間で「消去」され、リクエスト間で状態を共有するために使用することはできません。

59
mallyvai

この行

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

「with」キーワードを使用しているため、このループが実行されると、__exit__ AppContextクラスのメソッド。 this を参照してください。したがって、一度「foo」がポップアウトされます。それがあなたが再びそれを利用できない理由です。代わりに試すことができます:

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

以下を呼び出すまで、g.fooが利用可能である必要があります

ctx.pop()

キャッシュの目的でこれを使用したいかどうかはわかりません。

10
codegeek

私はflaskサーバーで使用する "モジュール全体の変数"のアイデアに似たようなことをしました。 「ユーザー」(送信者ソフトウェアであること)。

私の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 __== '__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

適切なマルチユーザーWebサーバー環境では動作しないことが予想されるため、注意して使用してください。

8
Johan Gov