web-dev-qa-db-ja.com

クラスメソッドをセロリタスクとして使用する

クラスのメソッドをDjango-celeryタスクとして使用し、@ taskデコレーターを使用してマークアップします。同じ状況が説明されています ここ 、Anand Jeyaharが尋ねました。こんな感じ

class A:
    @task
    def foo(self, bar):
        ...

def main():
    a = A()
    ...
    # what i need
    a.foo.delay(bar) # executes as celery task 
    a.foo(bar) # executes locally

問題は、このa.foo.delay(bar)のようなクラスインスタンスを使用しても、fooには少なくとも2つの引数が必要であり、selfポインターが欠落していることを意味します。

詳しくは:

  • 継承のため、クラスをmoduleに変換できません
  • メソッドはクラスメンバーに強く依存しているため、メソッドを作成できませんstatic
  • @taskデコレーターでタスクとしてclassをマークすると、クラス自体がタスクになり、run()からメソッドを実行できる可能性があります。メソッド、メソッド選択のためのキーとしていくつかの引数を使用しますが、それは私が望んでいるものではありません。
  • クラスのインスタンスを作成し、self引数としてメソッドに渡すと、メソッドの実行方法が変わりますnot通常の方法(テスト中)
  • たとえばコンストラクタからタスクを動的に登録する方法を見つけようとしましたが、セロリはワーカー間でコードを共有しているため、不可能なようです。

ご協力いただきありがとうございます!

40
eviltnan

Celeryは、バージョン3.0以降、メソッドをタスクとして使用するための実験的なサポートを提供しています。

このドキュメントはcelery.contrib.methodsにあり、注意すべきいくつかの注意事項にも言及しています。

http://docs.celeryproject.org/en/latest/reference/celery.contrib.methods.html

注意してくださいcontrib.methodsのサポートはCeleryから削除されました4.0以降

49
asksol

Jeremy Satterfieldには、クラスベースのタスクを作成するためのクリーンでわかりやすいチュートリアルがあります。確認できます こちら

魔法は基本的に、次のようなrun()メソッドを含むcelery.Taskクラスを拡張することです。

from celery import Task

class CustomTask(Task):
    ignore_result = True

    def __init__(self, arg):
        self.arg = arg

    def run(self):
        do_something_with_arg(self.arg)

そして、次のようにタスクを実行します:

your_arg = 3

custom_task = CustomTask()
custom_task.delay(your_arg)

ignore_result = Trueの部分が必要かどうかはわかりません。

7
Gokhan Sari

次の場合:

    a = A()

できるよ:

    A.foo.delay(a, param0, .., paramN)

乾杯

4
mihaicc

私にとっては、これがselfをメソッドに渡すだけなので、動作するのはcelery.current_appだけです。

したがって、これは次のようになります。

from celery import current_app
from celery.contrib.methods import task_method

class A:
@current_app.task(filter=task_method, name='A.foo')
def foo(self, bar):
    ...

異なるクラスに同じ名前のメソッドがある場合、名前を使用する必要があります。

1
Johnny Well