web-dev-qa-db-ja.com

flaskアプリの実行後に関数を呼び出すための適切なアプローチは何ですか?

とても簡単だと思ったことをする方法について少し混乱しています。 Flaskを使用して記述されたシンプルなアプリがあります。次のようになります。

from flask import Flask

app = Flask(__name__)

def _run_on_start(a_string):
    print "doing something important with %s" % a_string

@app.route('/')
def root():
    return 'hello world'

if __name__ == "__main__":
    if len(sys.argv) < 2:
        raise Exception("Must provide domain for application execution.")
    else:
        DOM = sys.argv[1]
        _run_on_start("%s" % DOM)
        app.run(debug=True)

私が見つけているのは、私の端末が_run_on_startで印刷ステートメントを出力しているが、他の通常のFlaskアプリデバッグコードではないことです。app.runの前に呼び出しを削除すると、さらに、起動時に_run_on_startの出力が2回繰り返されることがわかりますが、奇妙な出力なのか、関数が実際に2回呼び出されているのかはわかりません。

これは、app.runを呼び出す前に関数呼び出しを追加する正しい方法ではないと思います。 Flask docsを調べ、使用できるさまざまなデコレータの言及を見つけました。これにより、特定のリクエストの前後に関数を実行できますが、アプリサーバーが実行されているときに呼び出しを実行したいと思います。

さらに、このモジュールを別のモジュールから呼び出す場合、つまり__name__ != "__main__"の場合ではないので、_run_on_startへの呼び出しを取得できないことを理解しています。

ここで正しいアプローチは何ですか? CLと別のモジュールから開始する場合、どちらの場合でも?

31
Edwardr

関数からの重複出力は、リローダーで説明できます。最初に行うことは、メイン関数を新しいスレッドで開始して、ソースファイルを監視し、変更時にスレッドを再起動できるようにすることです。 use_reloader=Falseオプションでこれを無効にします。

別のモジュールからサーバーを起動するときに関数を実行できるようにするには、それを関数にラップし、その関数を他のモジュールから呼び出します。

def run_server(dom):
        _run_on_start("%s" % dom)
        app.run(debug=True, use_reloader=False)

if __name__ == '__main__':
    if len(sys.argv) < 2:
        raise Exception("Must provide domain for application execution.")
    else:
        DOM = sys.argv[1]
        run_server(DOM)

「正しいアプローチ」は、実際にここで達成しようとしていることに依存します。組み込みサーバーは、本番サーバーにデプロイする前にローカルのテスト環境でアプリケーションを実行するためのものです。そのため、別のモジュールから起動するという問題は、それ自体ではあまり意味がありません。

13
robots.jpg

おそらくあなたが探していたのはFlask.before_first_requestデコレータ。

@app.before_first_request
def _run_on_start(a_string):
    print "doing something important with %s" % a_string
47
the-happy-hippo
from flask import Flask

def create_app():
    app = Flask(__name__)
    def run_on_start(*args, **argv):
        print "function before start"
    run_on_start()
    return app

app = create_app()

@app.route("/")
def hello():
    return "Hello World!"
0
Peretz30