10
@celery.task
def my_task(my_object):
    do_something_to_my_object(my_object)


#in the code somewhere 
tasks = celery.group([my_task.s(obj) for obj in MyModel.objects.all()])
group_task = tasks.apply_async()

问题:celery 有什么东西可以检测小组任务的进度吗?我可以计算那里有多少任务以及已经处理了多少?

4

3 回答 3

6

修补外壳(ipython 的选项卡自动完成)我发现group_task(它是一个celery.result.ResultSet对象)有一个名为的方法completed_count,它给出了我所需要的。

还可以在http://docs.celeryproject.org/en/latest/reference/celery.result.html#celery.result.ResultSet.completed_count找到文档

于 2013-02-28T16:03:09.160 回答
4

这是基于@dalore's answer的完整工作示例。

首先tasks.py

import time
from celery import Celery, group

app = Celery('tasks', broker='pyamqp://guest@127.0.0.1//', backend='redis://localhost')

@app.task(trail=True)
def add(x, y):
    time.sleep(1)
    return x + y

@app.task(trail=True)
def group_add(l1, l2):
    return group(add.s(x1, x2) for x1, x2 in zip(l1, l2))()

使用 Docker 启动 redis 服务器:docker run --name my-redis -p 6379:6379 -d redis.

使用 Docker 启动 RabbitMQ docker run -d --hostname my-rabbit --name my-rabbit -p 5672:5672 rabbitmq:alpine:.

在单独的 shell 中启动单个进程 celery worker celery -A tasks worker --loglevel=info -c 1:.

然后运行下面的测试脚本。

from tasks import group_add
from tqdm import tqdm

total = 10

l1 = range(total)
l2 = range(total)
delayed_results = group_add.delay(l1, l2)
delayed_results.get()  # Wait for parent task to be ready.

results = []
for result in tqdm(delayed_results.children[0], total=total):
    results.append(result.get())
print(results)

您应该会看到类似下面的内容,其中进度条每秒增加 10%。

50%|#####     | 5/10 [00:05<00:05,  1.01s/it
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

最后,清理你的 redis 和 rabbitmq 容器。

docker stop my-rabbit my-redis
docker rm my-rabbit my-redis
于 2019-01-15T15:18:14.007 回答
1

阅读文档,AsyncResult有一种collect方法可以在结果进入时收集结果。

http://docs.celeryproject.org/en/latest/reference/celery.result.html#celery.result.AsyncResult.collect

from celery import group
from proj.celery import app

@app.task(trail=True)
def A(how_many):
    return group(B.s(i) for i in range(how_many))()

@app.task(trail=True)
def B(i):
    return pow2.delay(i)

@app.task(trail=True)
def pow2(i):
    return i ** 2

示例输出:

>>> from celery.result import ResultBase
>>> from proj.tasks import A

>>> result = A.delay(10)
>>> [v for v in result.collect()
...  if not isinstance(v, (ResultBase, tuple))]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

注意:Task.trail必须启用该选项,以便子列表存储在result.children. 这是默认设置,但为了说明而明确启用。

编辑:

经过进一步测试,发现虽然收集状态它将收集结果,但它仍在等待。我发现要获得进展,您需要获得孩子的结果,如下所示:

group_result = mygrouptask.delay().get()
for result in tqdm(group_result.children, total=count):
    yield result.get()

tqdm 在控制台中显示进度

mygrouptask 是一个返回芹菜组,如下所示:

return group(mytask.s(arg) for arg in args)()
于 2018-02-08T15:35:55.790 回答