12

Flask を使用して Web アプリケーションを構築しています。リクエストよりも長く続くリモート サービスへの接続を表すグローバル リソースを登録したいと考えています (この場合、接続は有効な SOAP 接続です)。最長 30 日間)。

もう 1 つの例は、ドライバーで接続プールを処理する MongoDB のようなデータベースであり、要求ごとに新しい接続を作成するとパフォーマンスが低下します。

アプリケーション コンテキストも要求コンテキストも、このタスクには適していないようです。

「別のオブジェクトをメインのフラスコ アプリケーションに渡す」という質問は、そのようなリソースをapp.configディクショナリに保存することを示唆しています。

4

2 に答える 2

5

アプリのインスタンス化と一致する必要がある場合は、Flask をサブクラス化する必要があります。アプリの作成がプロセスであることを考えると、オブジェクトにリソースをアタッチするだけの場合、これは実際にはあまり効果がありません。実のところ、アプリケーションがインスタンス化中にリソースを使用する必要がない場合は、おそらくこれを行う必要はありません。

class MyApp(Flask):
    def __init__(self, *args, **kwargs):
        setattr(self, 'some_resource', SomeResource())
        super(Flask, self).__init__(*args, **kwargs)

app = MyApp(__name__)
app.some_resource.do_something()

特定のユース ケースがない限り、ラッパー クラスを記述し、それをフラスコ拡張に変換し、モジュール レベルで作成して app.extensions に保存する方がよいでしょう。

class MyExtensions(object):
    def __init__(self, app=None):
        self.app = app
        if app is not None:
            self.init_app(app)

    def init_app(self, app):
        app.extensions['my_extension'] = SomeResource()

app = Flask(__name__)
my_extension = MyExtension(app)

次に、各アプリに独自のリソースを提供するか (上記のように)、現在のアプリを常に指している共有リソースを使用するかを選択できます。

from flask import _request_ctx_stack
try:
    from flask import _app_ctx_stack
except ImportError:
    _app_ctx_stack = None

stack = _app_ctx_stack or _request_ctx_stack

class SomeResource(object):
    def do_something(self):
        ctx = stack.top
        app = ctx.app
my_resource = SomeResource()
my_resource.do_something()

「Flaskオブジェクトがインスタンス化されると開始し、最初のリクエストが来ると暗黙的に終了する」ため、これをアプリケーションコンテキストに保存したくないと思います

代わりに、リソースをモジュール レベルで作成する必要があります。次に、それを拡張機能としてアプリケーションに添付するか、構成内であっても、それを簡単に拡張する方が一貫性があり論理的ですが、それをアプリケーションに添付できます。

于 2014-02-18T06:16:44.283 に答える
1

これは Python の問題です。Flask やその他の Web フレームワークがこれを許可しない/非常に困難にする理由は、同時実行のメモリ モデルが定義されていないためです。たとえば、Web サーバーが独自のプロセス (Gunicorn など) でリクエストを処理するとします。これにより、プロセスがメインプロセスから分岐し、「グローバル」変数がコピーされます。Windowsでサーバーを実行すると、フォークがないため、代わりにすべてのモジュールを再インポートする新しいプロセスが作成され、おそらくメインプロセス前に行われた変更を記憶していないクリーンなバージョンのグローバル状態が生成されます-スレッド。または、ネームガードの後ろで宣言すると、まったく見つかりません。

これを一貫して「正しく」行う方法は 2 つしかありません。1 つは、グローバルな状態を保持し、単一のスレッドに制限されている webapp を構築し、この webapp から他の webapp 呼び出し状態を持たせることです。

2 つ目は、Jython + スレッドを使用することです。Jython は JVM で実行されるため、共有状態を持つ明確に定義されたメモリ モデルを備えているため、コンテナ管理による同時実行などのすべての Java EE トリックを使用できます。

于 2016-09-19T14:54:56.600 に答える