セロリでタスクのステータスを確認する方法は?


92

タスクがセロリで実行されているかどうかを確認するにはどうすればよいですか(具体的には、セロリ-ジャンゴを使用しています)。

ドキュメントを読み、グーグルで検索しましたが、次のような通話が表示されません。

my_example_task.state() == RUNNING

私のユースケースは、トランスコーディング用の外部(Java)サービスがあることです。トランスコードするドキュメントを送信するときに、そのサービスを実行するタスクが実行されているかどうかを確認し、実行されていない場合は、それを(再)開始したいと思います。

私は現在の安定版-2.4を使用していると思います。

回答:


97

task_id(.delay()から指定)を返し、後でセロリインスタンスに状態を問い合わせます。

x = method.delay(1,2)
print x.task_id

要求されたら、このtask_idを使用して新しいAsyncResultを取得します。

from celery.result import AsyncResult
res = AsyncResult("your-task-id")
res.ready()

10
ありがとう。でも、アクセスできない場合はどうなりxますか?
Marcin、2012年

4
仕事をセロリのどこに入れますか?そこで、将来のジョブを追跡するためにtask_idを返す必要があります。
グレゴール

@Marcinとは異なり、この回答では静的メソッドTask.AsyncResult()をAsyncResultのファクトリとして使用していません。これはバックエンド構成を再利用するのに役立ちます。そうでない場合、結果を取得しようとするとエラーが発生します。
ArnauOrriols 2015年

2
@Chris @gregorコードに関する論争は、のインスタンス化ですasync_result。あなたのユースケースでは、すでにインスタンスを持っているので、準備完了です。しかし、タスクIDしか持っておらず、async_resultインスタンスをインスタンス化して呼び出すことができる必要がある場合はasync_result.get()どうなりますか?これはAsyncResultクラスのインスタンスですが、生のクラスは使用できません。でcelery.result.AsyncResultラップされた関数からクラスを取得する必要がありますapp.task()。あなたの場合あなたはそうするでしょうasync_result = run_instance.AsyncResult('task-id')
ArnauOrriols

1
but you cannot use the raw class celery.result.AsyncResult, you need to get the class from the function wrapped by app.task(). -これが実際に使われることになっていた方法だと思います。コードの読み取りを持っている:github.com/celery/celery/blob/...は
nevelis

70

作成AsyncResultタスクidからオブジェクトはあるに推奨される方法よくある質問あなたが持っている唯一のものは、タスクIDであるとき、タスクのステータスを取得します。

ただし、Celery 3.xの時点では、注意を払わないと人を傷つける可能性のある重要な警告があります。それは本当に特定のユースケースシナリオに依存します。

デフォルトでは、Celeryは「実行中」の状態を記録しません。

Celeryでタスクの実行を記録するには、に設定task_track_startedする必要がありますTrue。これをテストする簡単なタスクを次に示します。

@app.task(bind=True)
def test(self):
    print self.AsyncResult(self.request.id).state

ときtask_track_startedFalseデフォルトである、状態のショーがあるPENDINGタスクが開始されているにもかかわらず。に設定task_track_startedするTrueと、状態はSTARTED

状態 PENDINGは「わからない」という意味です。

AsyncResult状態を持ちますPENDINGないセロリは、タスクのステータスを知らない以上という意味では何もしません。これには、さまざまな理由が考えられます。

1 AsyncResultつには、無効なタスクIDを使用して構築される可能性があります。そのような「タスク」は、Celeryによって保留中と見なされます。

>>> task.AsyncResult("invalid").status
'PENDING'

では、明らかに無効なIDをにフィードする人は誰もいませんAsyncResult。十分に公平ですAsyncResultが、実行には成功したが、Celeryが存在することを忘れてしまったタスクも考慮するPENDING効果があります繰り返しになりますが、一部のユースケースでは、これが問題になることがあります。問題の一部は、結果のバックエンドでの「墓石」の可用性に依存しているため、Celeryがタスクの結果を保持するように構成されている方法に依存しています。使用方法(「墓石には」データチャンクのためのセロリドキュメントの長期使用は、タスクが終了したか記録が。ということである)AsyncResult、すべての場合では動作しませんtask_ignore_resultISTrue。さらに厄介な問題は、Celeryがデフォルトでトゥームストーンを期限切れにすることです。のresult_expiresデフォルトの設定は24時間に設定されています。したがって、タスクを起動し、長期保存でIDを記録し、さらに24時間後に、それを使用しAsyncResultてを作成すると、ステータスはになりますPENDING

すべての「実際のタスク」はそのPENDING状態から始まります。したがってPENDING、タスクを取得することは、タスクが要求されたが、(何らかの理由で)これより先に進むことはなかったことを意味する場合があります。または、タスクは実行されたがセロリがその状態を忘れたことを意味する場合があります。

痛い!AsyncResultうまくいきません。他に何ができますか?

タスク自体を追跡するよりも、目標を追跡することを好みます。私はいくつかのタスク情報を保持していますが、それは目標を追跡することの本当に二次的なものです。目標はセロリから独立したストレージに保存されます。要求が計算を実行する必要がある場合、達成されたいくつかの目標に依存し、目標がすでに達成されているかどうかをチェックし、達成されている場合は、このキャッシュされた目標を使用します。それ以外の場合は、目標に影響を与えるタスクを開始し、 HTTPリクエストを、結果を待つ必要があることを示す応答であるクライアント。


上記の変数名とハイパーリンクは、Celery 4.x用です。3.xでは、対応する変数やハイパーリンクは以下の通りですCELERY_TRACK_STARTEDCELERY_IGNORE_RESULTCELERY_TASK_RESULT_EXPIRES


後で結果を確認したい場合(多分別のプロセス内でも)、自分の実装を使用した方がよいでしょうか?結果をデータベースに手動で保存しますか?
フランクリンYu

はい、「目標」の追跡と「タスク」の追跡を分離します。「ある目標に依存する計算を行う」と書いた。通常、「目標」も計算です。たとえば、記事Xをユーザーに表示したい場合は、XMLからHTMLに変換する必要がありますが、その前にすべての書誌参照を解決しておく必要があります。(Xはジャーナル記事のようなものです。)目標「すべての書誌参照が解決された記事X」が存在するかどうかを確認し、希望する目標を計算したセロリタスクのタスクステータスを確認するのではなく、それを使用します。
Louis

そして、「すべての書誌的参照が解決された記事X」という情報は、メモリキャッシュに格納され、eXist-dbデータベースに格納されます。
Louis

61

すべてのTaskオブジェクトには、.requestそのAsyncRequestオブジェクトを含むプロパティがあります。したがって、次の行はTaskの状態を示していますtask

task.AsyncResult(task.request.id).state

2
タスクの進捗率を保存する方法はありますか?
パトリック

4
これを行うと、タスクが完了するのに十分な時間待機しても、永久にPENDING AsyncResultが返されます。これに状態の変化を見させる方法はありますか?私のバックエンドは構成されていると思います。CELERY_TRACK_STARTED= Trueを無効に設定してみました。
dstromberg

1
@dstromberg残念ながら、これが私にとって問題となってから4年になります。ほぼ確実に、状況を追跡するようにセロリを構成する必要があります。
Marcin 2016

16

また、カスタム状態を作成して、タスク実行の値を更新することもできます。この例はドキュメントからのものです:

@app.task(bind=True)
def upload_files(self, filenames):
    for i, file in enumerate(filenames):
        if not self.request.called_directly:
            self.update_state(state='PROGRESS',
                meta={'current': i, 'total': len(filenames)})

http://celery.readthedocs.org/en/latest/userguide/tasks.html#custom-states


11

古い質問ですが、最近この問題に遭遇しました。

task_idを取得しようとしている場合は、次のように実行できます。

import celery
from celery_app import add
from celery import uuid

task_id = uuid()
result = add.apply_async((2, 2), task_id=task_id)

これでtask_idが正確にわかったので、それを使用してAsyncResultを取得できます。

# grab the AsyncResult 
result = celery.result.AsyncResult(task_id)

# print the task id
print result.task_id
09dad9cf-c9fa-4aee-933f-ff54dae39bdf

# print the AsyncResult's status
print result.status
SUCCESS

# print the result returned 
print result.result
4

3
独自のタスクIDを作成してに渡す必要はまったくありませんapply_async。によって返されるオブジェクトapply_async は、AsyncResultCeleryが生成したタスクのIDを持つオブジェクトです。
Louis

1
私が間違っている場合は修正してください。ただし、同じ入力を取得するすべての呼び出しが同じUUIDを取得できるように、一部の入力に基づいてUUIDを生成することが役立つ場合がありますか?IOW、たまにtask_idを指定すると役立つ場合があります。
dstromberg

1
@dstromberg OPが尋ねる質問は「タスクのステータスを確認するにはどうすればよいですか」であり、ここでの回答は「task_idを取得しようとしている場合...」です。タスクのステータスをチェックすることも、タスクIDを自分で生成するtask_id必要もありません。あなたのコメントでは、「タスクのステータスを確認するにはどうすればよいですか」や「task_idを取得しようとしている場合...」必要以上の理由があると想像しましたが、そうではありませんが、そうではありません。ここで(さらに、タスクIDの生成に使用しても、Celeryがデフォルトで行うこと以外は何実行されませ。)uuid()
Louis

OPが予測可能なタスクIDを取得する方法を具体的に尋ねなかったことに同意しますが、OPの質問への答えは現在「タスクIDを追跡してxを実行する」です。さまざまな状況でタスクIDを追跡することは実際的ではないため、回答が実際には十分ではないように思えます。この答えは、@ dstrombergが指摘するのと同じ理由で、その理由で動機付けされたかどうかに関係なく、(他の指摘された制限を克服できる場合)私のユースケースを解決するのに役立ちます。
クレイトン


1

2020年の回答:

#### tasks.py
@celery.task()
def mytask(arg1):
    print(arg1)

#### blueprint.py
@bp.route("/args/arg1=<arg1>")
def sleeper(arg1):
    process = mytask.apply_async(args=(arg1,)) #mytask.delay(arg1)
    state = process.state
    return f"Thanks for your patience, your job {process.task_id} \
             is being processed. Status {state}"

0

試してください:

task.AsyncResult(task.request.id).state

これにより、Celeryタスクのステータスが提供されます。CeleryタスクがすでにFAILURE状態にある場合は、例外がスローされます。

raised unexpected: KeyError('exc_type',)



0

に役立つ情報が見つかりました

セロリプロジェクトワーカーズガイド検査員

私の場合、Celeryが実行されているかどうかを確認しています。

inspect_workers = task.app.control.inspect()
if inspect_workers.registered() is None:
    state = 'FAILURE'
else:
    state = str(task.state) 

あなたはあなたのニーズを得るためにinspectで遊ぶことができます。


0
  • まず、あなたのセロリアプリで:

vi my_celery_apps / app1.py

app = Celery(worker_name)
  • 次に、タスクファイルに変更し、セロリアプリモジュールからアプリをインポートします。

viタスク/task1.py

from my_celery_apps.app1 import app

app.AsyncResult(taskid)

try:
   if task.state.lower() != "success":
        return
except:
    """ do something """


-1

上記とは別に、フラワータスクを使用したプログラムによるアプローチのステータスは簡単に確認できます。

セロリイベントを使用したリアルタイム監視。Flowerは、Celeryクラスターを監視および管理するためのWebベースのツールです。

  1. タスクの進捗状況と履歴
  2. タスクの詳細を表示する機能(引数、開始時間、実行時間など)
  3. グラフと統計

公式文書: 花-セロリ監視ツール

インストール:

$ pip install flower

使用法:

http://localhost:5555

-1
res = method.delay()
    
print(f"id={res.id}, state={res.state}, status={res.status} ")

print(res.get())

2
回答としてコードだけを投稿するのではなく、コードの機能と質問の問題の解決方法を説明してください。説明付きの回答は、通常、より効果的で質が高く、賛成票を集める可能性が高くなります。
Mark Rotteveel
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.