如何在Celery中检查任务状态?


92

如何检查一项任务是否在celery中运行(特别是我正在使用celery-django)?

我已经阅读了文档,并且已经在google上搜索了,但是看不到像这样的呼叫:

my_example_task.state() == RUNNING

我的用例是我有一个外部(java)服务来进行代码转换。当我发送要进行代码转换的文档时,我想检查运行该服务的任务是否正在运行,如果没有运行,请(重新)启动它。

我相信我使用的是当前的稳定版本-2.4。

Answers:


97

返回task_id(由.delay()提供),然后向celery实例询问状态:

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以跟踪将来的作业。
Gregor 2012年

与@Marcin的方法不同,此答案不使用静态方法Task.AsyncResult()作为AsyncResult的工厂,该方法有助于重用后端配置,否则在尝试获取结果时会引发错误。
ArnauOrriols

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_startedTrue。这是一个测试此任务的简单任务:

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

task_track_startedis False为默认值时,PENDING即使任务已开始,状态显示仍为。如果设置task_track_startedTrue,则状态为STARTED

状态PENDING表示“我不知道”。

一个AsyncResult与状态PENDING并不意味着什么,更重要的是芹菜不知道任务的状态。这可能是由于多种原因造成的。

一方面,AsyncResult可以使用无效的任务ID进行构造。这些“任务”将被Celery视为待处理:

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

好的,因此没有人可以将明显无效的ID提供给AsyncResult。足够公平,但它也有效果,AsyncResult也将考虑已成功运行但Celery已忘记存在的任务PENDING同样,在某些用例场景中,这可能是个问题。问题的一部分取决于Celery如何配置为保留任务结果,因为它取决于结果后端中“逻辑删除”的可用性。(“ Tombstones”是Celery文档中使用的术语,用于记录任务如何完成的数据块。)使用is AsyncResult根本不起作用。一个更令人烦恼的问题是,Celery默认使墓碑过期。的task_ignore_resultTrueresult_expires设置默认设置为24小时。因此,如果您启动任务并将ID记录在长期存储中,并且在24小时后再创建一个ID AsyncResult,则状态为PENDING

所有“实际任务”都从该PENDING状态开始。因此,PENDING继续执行某项任务可能意味着该任务已被请求,但再也没有进一步进展了(无论出于何种原因)。否则可能意味着任务已执行,但Celery忘记了状态。

哎哟! AsyncResult不会为我工作。我还可以做些什么?

与跟踪任务本身相比,我更喜欢跟踪目标。我确实保留了一些任务信息,但这实际上是跟踪目标的第二要务。目标存储在独立于Celery的存储中。当请求需要执行计算取决于某个目标已经实现时,它会检查目标是否已经实现,如果是,则使用此缓存的目标,否则将启动将影响目标的任务,并发送至向HTTP请求发出响应的客户端,指示其应等待结果。


上面的变量名称和超链接适用于Celery4.x。在3.x中相应的变量和超链接是:CELERY_TRACK_STARTEDCELERY_IGNORE_RESULTCELERY_TASK_RESULT_EXPIRES


因此,如果我想稍后再检查结果(甚至在另一个过程中),那么我最好使用自己的实现?将结果手动存储到数据库中?
富兰克林于

是的,我将跟踪“目标”与跟踪“任务”分开。我写了“执行取决于某个目标的计算”。通常,“目标”也是一种计算。例如,如果要向用户显示文章X,则必须将其从XML转换为HTML,但是在此之前,我必须已解析所有书目参考。(X就像期刊上的文章一样。)我检查目标“具有所有参考文献索引的文章X已解决”是否存在,并使用该目标,而不是尝试检查可以计算出所需目标的Celery任务的任务状态。
路易(Louis)

信息“已解决所有参考文献的文章X”存储在内存缓存中,并存储在eXist-db数据库中。
路易(Louis)

61

每个Task对象都有一个.request属性,其中包含AsyncRequest对象。因此,以下行给出了Task的状态task

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

2
有没有办法存储任务进度的百分比?
patrick

4
当我这样做时,即使我等待足够长的时间来完成任务,我也会得到一个永久的PENDING AsyncResult。有没有办法使此可见状态发生变化?我相信我的后端已配置,并且我尝试将CELERY_TRACK_STARTED =设置为True无效。
dstromberg '16

1
@dstromberg不幸的是,这对我来说已经有4年了,所以我无能为力。您几乎肯定需要配置celery来跟踪状态。
Marcin


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 是一个AsyncResult对象,它确实具有Celery生成的任务的ID。
路易

1
如果我错了,请纠正我,但是有时基于某些输入生成UUID有时不是有用的,这样所有获得相同输入的调用都将获得相同的UUID吗?IOW,有时指定您的task_id很有用。
dstromberg'8

1
@dstromberg OP提出的问题是“如何检查任务状态”,此处的答案是“如果您要获取task_id ...”。既不检查任务状态,也不获取任务task_id要求您自己生成任务ID。在您的评论中,您已经想到了一个超出 “我如何检查任务状态”和“如果您试图获取task_id ...”的原因,如果您有此需要,那是很好的,但事实并非如此(此外,uuid()用于生成任务ID绝对不会超出Celery的默认设置。)
路易(Louis

我同意OP并没有具体询问如何获取可预测的任务ID,但是OP的问题的答案目前是“跟踪任务ID并执行x”。在我看来,在许多情况下跟踪任务ID都是不切实际的,因此答案可能实际上并不令人满意。出于@dstromberg指出的相同原因,此答案可以帮助我解决用例(如果我可以克服其他指出的限制),无论它是否出于该原因。
claytond


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 Task已经处于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) 

您可以通过检查来满足您的需求。


0
  • 首先,在您的芹菜APP中:

vi my_celery_apps / app1.py

app = Celery(worker_name)
  • 接下来,切换到任务文件,从celery应用程序模块导入应用程序。

vi任务/ task1.py

from my_celery_apps.app1 import app

app.AsyncResult(taskid)

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


-1

除了上述编程方法之外,可以轻松查看使用花任务的状态。

使用Celery Events进行实时监控。Flower是用于监视和管理芹菜群集的基于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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.