django celery:如何设置以编程方式以特定间隔运行的任务

时间:2011-08-24 08:32:02

标签: python django celery django-celery

我发现我可以将任务设置为在here的特定时间以特定时间间隔运行,但这只是在任务声明期间完成的。如何设置动态定期运行的任务?

4 个答案:

答案 0 :(得分:8)

计划是derived from a setting,因此在运行时似乎是不可变的。

您可以使用Task ETAs完成您要找的内容。这可以保证您的任务在所需的时间之前不会运行,但不保证在指定的时间运行任务 - 如果工作人员在指定的ETA处超载,则任务可能会在稍后运行

如果这个限制不是问题,你可以编写一个首先运行的任务,如:

@task
def mytask():
    keep_running = # Boolean, should the task keep running?
    if keep_running:
        run_again = # calculate when to run again
        mytask.apply_async(eta=run_again)
    # ... do the stuff you came here to do ...

这种方法的主要缺点是你依靠taskstore来记住飞行中的任务。如果其中一个在启动下一个之前失败,则该任务将永远不会再次运行。如果您的代理没有持久化到磁盘并且它已经死亡(使用它执行所有正在进行的任务),那么这些任务都不会再次运行。

你可以通过某种事务记录和周期性的“保姆”任务来解决这些问题,这项任务的目的是找到这样的重复任务,这些任务会死于不合时宜的死亡并使它们复活。

如果我必须实施你所描述的内容,我认为这就是我接近它的方式。

答案 1 :(得分:2)

celery.task.base.PeriodicTask定义is_due,确定下次运行的时间。您可以覆盖此函数以包含自定义动态运行逻辑。请参阅此处的文档:http://docs.celeryproject.org/en/latest/reference/celery.task.base.html?highlight=is_due#celery.task.base.PeriodicTask.is_due

一个例子:

import random
from celery.task import PeriodicTask

class MyTask(PeriodicTask):

    def run(self, **kwargs):
        logger = self.get_logger(**kwargs)
        logger.info("Running my task")

    def is_due(self, last_run_at):
        # Add your logic for when to run. Mine is random
        if random.random() < 0.5:
            # Run now and ask again in a minute
            return (True, 60)
        else:
            # Don't run now but run in 10 secs
            return (True, 10)

答案 2 :(得分:0)

http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html

我认为你不能动态地制作它...最好的方法是在任务中创建任务:D

例如,你想要在X秒之后运行一些东西,然后用x秒延迟创建新任务,并在此任务中为N * X秒延迟创建另一个任务......

答案 3 :(得分:0)

这可以帮助你... http://celery.readthedocs.org/en/latest/faq.html#can-i-change-the-interval-of-a-periodic-task-at-runtime

一旦您定义了自定义计划,请按照asksol上面的建议将其分配给您的任务。

CELERYBEAT_SCHEDULE = {    
    "my_name": {
        "task": "myapp.tasks.task",
        "schedule": myschedule(),    
    }
}

如果您希望您的日程安排比每五分钟更新一次,您可能还想修改CELERYBEAT_MAX_LOOP_INTERVAL。