8

私のモデルの後処理はpost_save信号を使用しています:

from django.core.signals import request_finished
from django.dispatch import receiver
from models import MyModel
from pipeline import this_takes_forever


@receiver(post_save, sender=MyModel)
def my_callback(sender, **kwargs):
    this_takes_forever(sender)

ルーチンは IO を行うので、this_takes_foreverリクエストをブロックしすぎないように延期したいと考えています。

これは、新しいasyncioモジュールの優れた使用例だと思いました。しかし、私はプロセス全体を理解するのに苦労しています。

次のように信号受信機を適応させることができるはずだと思います:

@receiver(post_save, sender=MyModel)
def my_callback(sender, **kwargs):
    loop = asyncio.get_event_loop()
    loop.run_until_complete(this_takes_forever(sender))
    loop.close()

Providedthis_takes_foreverは、コルーチンにも適合しています。

@coroutine
def this_takes_forever(instance):
    # do something with instance
    return instance

これは魔法のように聞こえます。そして実際には、次のように停止しますAssertionError

AssertionError at /new/
There is no current event loop in thread 'Thread-1'.

このコンテキストでは、どこからループを開始すればよいかわかりません。誰かがこのようなことを試しましたか?

4

1 に答える 1

6

あなたの場合、何の利益も得られません:

@receiver(post_save, sender=MyModel)
def my_callback(sender, **kwargs):
    this_takes_forever(sender)

に等しい

@receiver(post_save, sender=MyModel)
def my_callback(sender, **kwargs):
    loop = asyncio.get_event_loop()
    loop.run_until_complete(this_takes_forever(sender))
    loop.close()

実行時間の観点から。loop.run_until_completeコルーチン呼び出しの終了を待機するためthis_takes_forever(sender)、前者と同様に 2 番目のケースでも同期呼び出しが行われます。

概要AssertionError: Django アプリをマルチスレッド モードで起動しますがasyncio、メイン スレッドに対してのみデフォルトのイベント ループを作成します。asyncio コードを呼び出す必要があるユーザー作成スレッドごとに新しいループを登録する必要があります。

しかし、繰り返しますが、asyncio は特定の問題を解決できません。Django と互換性がないだけです。

Django の標準的な方法は、実行時間の長いコードをセロリ タスクに延期することです ( http://www.celeryproject.org/を参照) 。

于 2014-05-22T16:18:22.733 に答える