2015-11-19 224 views
22

Djangoサーバーの起動時にいくつかのコードを実行したいが、そのコードを1回だけ実行したい。現在、サーバーを起動すると2回実行されます。DjangoでAppConfig.ready()メソッドが2回実行されるのを避ける方法

あなたは正確に1回実行する必要があります再実行し コードを防ぐために、あなたのAppConfigクラスにフラグを置く必要があります。Documentationはこれが起こるかもしれないと言います。

どのようにこれを達成するためのアイデアですか?以下のPrint文は依然として2回実行されます。

from django.apps import AppConfig 
import app.mqtt 
from apscheduler.schedulers.background import BackgroundScheduler 

class MyAppConfig(AppConfig): 
    name = 'app' 
    verbose_name = "HomeIoT" 
    run_already = False 

    def ready(self): 
     if MyAppConfig.run_already: return 
     MyAppConfig.run_already = True 
     print("Hello") 
+0

はそのインデントが正しいですか?'ready'はMyAppConfigクラスの内側にあるはずです。 –

+1

あなたは正しいです。それはちょうどコピー/貼り付けの間違いだった。それを私が直した。 – Koooop

+2

'--noreload'を実行すると二重印刷が行われますか? – AKX

答えて

-1

クラス変数ではなくインスタンス変数を使用してください。例:

class MyAppConfig(AppConfig): 
    run_already = False 

    def ready(self): 
     if not self.run_already: 
      print('Hello, world!') 
      self.run_already = True 
+4

アドバイスをいただきありがとうございますが、残念ながらこれは役に立ちません。 – Koooop

+0

これは、問題 – user3479125

+0

と同じように見えますが、奇妙ですが、この解決策は主な最新文書に従っています。この場合は、冪等のメソッドを記述するか、AppConfigクラスにフラグを設定してください。 ' – user3479125

2

ロックを実装する必要があります。これは単純な問題ではなく、プロセスとスレッドを処理するときに解決策が自然に感じられることはありません。

ファイルロック:Ensure a single instance of an application in Linux(スレッドはデフォルトでファイルロックを共有するので、この回答をスレッドのアカウントに拡張する必要があることに注意してください)。

Pythonパッケージは、ファイルロックの実装をカプセル化するtendoと呼ばれる使用していますこの答えもあります:https://stackoverflow.com/a/1265445/181907

ジャンゴ自体はdjango.core.files.locksにユーティリティをロックする抽象化されたポータブルファイルを提供します。

2

Robertoは、デフォルトのauto_reload機能を使用する場合は、runserverコマンドでサーバーを実行するときにこれを行うためにロックを実装する必要があると述べています。

Djangoはスレッド化によってauto_reloadを実装しているため、AppConfigを2つの別々のスレッド、つまりメインの 'command/watch'スレッドとサーバーを実行する 'reload'スレッドにインポートします。モジュールにprintステートメントを追加すると、実際にこれが表示されます。 'メイン'スレッドはAppConfigファイルをBaseCommandの一部としてロードし、 'reload'スレッドはサーバの起動時に再度ロードします。

これらのスレッドの両方で実行できないコードがある場合、オプションはいくらか制限されます。スレッドロックを実装して、 'reload'スレッドがready()を実行しないようにすることができます。実稼働環境に移行してサーバーを稼働させることができます(例えば、Gunicornはテストのためにセットアップするのが非常に簡単です)。 ready()を使用するのではなく、別の方法でメソッドを呼び出すことができます。

私は適切な環境に移行するようお勧めしますが、最良の選択肢は実際にあなたが呼んでいる方法が正確に何をするかによって異なります。

2

python manage.py runserver Djangoを使用すると、実際の開発サーバー用と、コードが変更されたときにアプリケーションを再ロードする2つのプロセスが開始されます。

はまた、reloadオプションなしでサーバーを起動することができ、あなたが唯一のプロセスが実行は一度だけ実行されます表示されます。

python manage.py runserver --noreload 

You can see this links,it resolve that ready() method running twice in Django

関連する問題