设置定时任务?

585

我一直在使用Django开发一个Web应用程序,想知道是否有方法可以定期运行任务。

基本上,我只想在数据库中进行一些计算/更新,并在固定时间自动执行,但是我似乎找不到任何关于如何执行此操作的文档。

有人知道如何设置吗?

为了澄清:我知道我可以设置一个cron作业来完成这个操作,但我想知道Django是否提供了这个功能。我希望人们能够轻松部署这个应用程序而不需要进行太多配置(最好是零配置)。

我考虑通过简单地检查是否应该自上次请求发送到站点以来运行作业来触发这些操作“回溯”,但我希望有更加简洁的解决方案。


你对这个有什么看法?https://github.com/reavis/django-cron - Domenico Monaco
6
Huey 需要在这里提一下。它与 Django 配合起来非常容易安装。 - Brandon Bertelsen
26个回答

405

我采用的一种解决方案是:

1)创建一个自定义管理命令,例如:

python manage.py my_cool_command

2)在Linux上使用cron,在Windows上使用at在所需的时间运行我的命令。

这是一个简单的解决方案,不需要安装庞大的AMQP堆栈。然而,像其他答案中提到的Celery这样的工具确实有很多优点。特别是,使用Celery时,不必将应用程序逻辑分散到crontab文件中,这非常好。但是对于小型到中型的应用程序以及您不想要许多外部依赖项的情况,cron解决方案非常有效。

编辑:

在Windows的较新版本中,at命令已被弃用,适用于Windows 8、Server 2012及以上版本,可以使用schtasks.exe进行相同的操作。

**** 更新 **** 以下是编写自定义管理命令的Django文档的新链接


7
这是否是一种不使用外部服务,而仅利用运行中的Django框架进程来完成此操作的方法? - sergzach
4
@Brian_Neal django_cron 应用程序。 - sergzach
2
请帮助我理解如何在虚拟环境中使用cron在每个月的最后一天运行一个管理命令。 - mmrs151
2
@sergzach 我跟进了这个评论,结果发现有两个同名的包。一个是 Google Code 上的 django-cron,另一个是 Github 上的 django-cron。它们略有不同,但都很有趣。两者都允许以“Djangonic”的方式定义 cron。第一个包有点老,旨在在没有外部任务(即 cron)的情况下工作。另一方面,第二个包需要您设置 cron 来运行 python manage.py runcrons,然后运行您定义和注册的所有 crons。 - floer32
1
@sergzach 我假设你在提到第一个,即 "Google Code 上的 django-cron"。你是对的。这就是为什么我选择第二个 "GitHub 上的 django-cron" 的原因,因为它可以使得你只需要一个简单的 crontab 设置和管理 - 只有一个 crontab,引用了管理命令 - 但是由于你使用了一个单独的 cron 进程,所以你避免了这个同步问题(至少据我所知)。 - floer32
显示剩余4条评论

172

Celery 是一个基于 AMQP(RabbitMQ)构建的分布式任务队列。它还能像 cron 一样处理定时任务(请参阅定期任务)。根据您的应用程序,这可能值得一试。

Celery 在 django 中非常容易设置(文档),而且定期任务在出现停机情况时会跳过错过的任务。Celery 还具有内置的重试机制,以防任务失败。


55

我们已经开源了我认为是一个有结构的应用程序,这与Brian上面提到的解决方案有关。我们非常乐意接受任何/所有反馈!

https://github.com/tivix/django-cron

它带有一个管理命令:

./manage.py runcrons

这就是工作的方式。每个cron都被建模为一个类(因此全部都是面向对象的),每个cron以不同的频率运行,我们确保相同类型的cron不会并行运行(以防cron本身运行的时间比其频率长!)


7
抱歉,我知道这可能是一个愚蠢的问题,但是这个程序能否通过"at"在Windows上运行,还是专门设计为与"cron"配合使用? - Bruno Finger
1
@BrunoFinger 它使用Python类,因此基本上只需要Python,不需要特定于平台的命令。 - Hagai Wild

37
如果你使用标准的POSIX操作系统,你可以使用cron
如果你使用Windows操作系统,你可以使用at
编写一个Django管理命令,以执行以下步骤:
  1. 确定用户所在的平台。

  2. 执行适用于用户的“AT”命令,或者更新用户的crontab。


12
如果可能的话,我希望能够将它整合到我的 Django 应用程序中。 - TM.
@TM: "rolled-up into my django app" 是什么意思?请澄清你的问题。 - S.Lott
12
我希望人们能够轻松部署此应用程序,而无需自己设置cron作业。 - TM.
1
你可以将 cron 接口嵌入你的应用程序中。 - monkut
BSD、Mac 和任何类 Unix 操作系统都有 cron。 - DylanYoung

23

有趣的新可插拔Django应用程序: django-chronograph

你只需要添加一个cron条目作为计时器,就可以在Django管理界面中非常方便地运行脚本。


2
django-chronograph已经不再维护。它的分支做得更好:https://github.com/chrisspen/django-chroniker - Menda

16

看看Django Poor Man's Cron,这是一个Django应用程序,利用垃圾邮件机器人、搜索引擎索引机器人等来按照大致规律间隔运行计划任务。

参见:http://code.google.com/p/django-poormanscron/


2
这也假设您的Django应用程序可以从Web访问,而对于部署在局域网和VPN上的情况则不适用。 - TimH - Codidact

15

我有一段时间以前也有完全相同的要求,最终使用 APScheduler (用户指南) 解决了这个问题。

它使作业调度变得超级简单,并将其与某些代码的基于请求的执行保持独立。以下是一个简单的示例。

from apscheduler.schedulers.background import BackgroundScheduler

scheduler = BackgroundScheduler()
job = None

def tick():
    print('One tick!')\

def start_job():
    global job
    job = scheduler.add_job(tick, 'interval', seconds=3600)
    try:
        scheduler.start()
    except:
        pass

希望这能帮助到某些人!


2
你如何将它包含在Django应用程序中?你是在wsgi.py中创建调度程序吗?还是作为完全独立的进程运行? - tbrlpld
嘿@PhoenixDev,我该如何在Django项目结构中使用它?我应该把这个调度器放在哪里?感激任何建议。 - P S Solanki

11

如果你想通过cron来运行管理命令,Brian Neal提出的建议很好,但如果你想要更强大的东西(不像Celery那么复杂),我建议你看看类似于Kronos这样的库:

# app/cron.py

import kronos

@kronos.register('0 * * * *')
def task():
    pass

11

Django APScheduler用于定时任务调度。Advanced Python Scheduler (APScheduler)是一个Python库,它允许您安排Python代码稍后执行,无论是仅一次还是周期性地执行。您可以随意添加新作业或删除旧作业。

注意:我是这个库的作者

安装APScheduler

pip install apscheduler

调用查看文件函数

文件名:scheduler_jobs.py

def FirstCronTest():
    print("")
    print("I am executed..!")

配置调度程序

制作execute.py文件并添加以下代码

from apscheduler.schedulers.background import BackgroundScheduler
scheduler = BackgroundScheduler()

在这里编写您的函数。调度程序函数编写在 scheduler_jobs 中。

import scheduler_jobs 

scheduler.add_job(scheduler_jobs.FirstCronTest, 'interval', seconds=10)
scheduler.start()

链接文件以便执行

现在,在Url文件底部添加以下行

import execute

10
RabbitMQ和Celery比Cron拥有更多的功能和任务处理能力。如果任务失败不是问题,而且您认为在下一次调用中会处理破损的任务,那么Cron就足够了。
Celery和AMQP可以让您处理破损的任务,并由另一个worker(Celery workers监听下一个要处理的任务)再次执行,直到达到任务的max_retries属性。甚至可以在失败时调用任务,例如记录失败或在达到max_retries后向管理员发送电子邮件。
当需要扩展应用程序时,您还可以分发Celery和AMQP服务器。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接