8

Flaskを使用してPythonWebアプリケーションを作成しています。私のアプリケーションは起動時に別のサーバーへの接続を確立し、バックグラウンドで定期的にそのサーバーと通信します。

Flaskの組み込みデバッガー(debug = Falseでapp.runを呼び出す)を使用しない場合は、問題ありません。

組み込みのデバッガーを使用する場合(debug = Trueでapp.runを呼び出す)、Flaskは同じコードで2番目のPythonプロセスを開始します。最終的にHTTP接続をリッスンし、アプリケーションが想定どおりに動作するのは子プロセスであり、デバッガーが起動したときに親が監視するためにそこにいると思います。

しかし、これは両方のプロセスで実行される私のスタートアップコードに大混乱をもたらします。最終的に、外部サーバーへの2つの接続、同じログファイルへの2つのプロセスのログ記録が発生し、通常、それらは相互にトリップします。

app.run()を呼び出す前に実際の作業を行うべきではないと思いますが、この初期化コードをどこに置くべきですか(デバッガーモードに関係なく、Flaskプロセスグループごとに1回だけ実行したいのですが、必要です起動時に実行し、クライアントの要求とは無関係に実行しますか?

「Flaskの自動リロードと長時間実行スレッド」に関するこの質問は、多少関連していますが、多少異なり、答えは役に立ちませんでした。(私もデーモンスレッドとしてマークされた別の長時間実行スレッドを持っていますが、リローダーが起動すると強制終了されますが、解決しようとしている問題は、リロードが発生する前です。私は関係ありません。リロード;私は余分なプロセスと、親プロセスで不要なコードを実行しないようにする正しい方法に関心があります。)

4

1 に答える 1

9

この動作は、Flask自体ではなく、Werkzeugによるものであり、リローダーに関連していることを確認しました。これは、Werkzeugのserving.pyで確認できます。run_simple()では、use_reloaderがtrueの場合、subprocess.call(sys.executable)を設定した後、ヘルパー関数run_with_reloader()/ restart_with_reloader()を介してmake_serverを呼び出します。サブプロセスによって継承される環境の環境変数WERKZEUG_RUN_MAIN。

私はかなり醜いハックでそれを回避しました:私のメイン関数で、wsgiアプリケーションオブジェクトを作成してapp.run()を呼び出す前に、WERKZEUG_RUN_MAINを探します:

if use_reloader and not os.environ.get('WERKZEUG_RUN_MAIN'):
    logger.warning('startup: pid %d is the werkzeug reloader' % os.getpid())
else:
    logger.warning('startup: pid %d is the active werkzeug' % os.getpid()
    # my real init code is invoked from here

Werkzeugがサービスを開始する前に呼び出されるメソッドがある場合、これはアプリケーションオブジェクトの内部から行う方がよいと思います。しかし、私はそのような方法を知りません。

これはすべて要約すると、Werkzeugのrun_simple.pyでは、make_server()。serve_forever()への最終的な呼び出しは1つだけですが、run_simple()への呼び出しは2つある可能性があります(その時点までの呼び出しスタック全体) make_server()に到達する前に。

于 2012-07-20T06:09:49.850 に答える