ChatGPT解决这个技术问题 Extra ChatGPT

设置计划的工作?

我一直在使用 Django 开发一个网络应用程序,我很好奇是否有办法安排作业定期运行。

基本上我只想通过数据库运行并自动定期进行一些计算/更新,但我似乎找不到任何关于这样做的文档。

有谁知道如何设置这个?

澄清一下:我知道我可以设置一个 cron 作业来执行此操作,但我很好奇 Django 中是否有提供此功能的某些功能。我希望人们能够自己部署这个应用程序,而不必做太多配置(最好是零)。

我已经考虑通过简单地检查自上次将请求发送到站点以来是否应该运行作业来“追溯”触发这些操作,但我希望有一些更清洁的东西。

你觉得这怎么样? github.com/reavis/django-cron
github.com/coleifer/huey 休伊需要在这里提及。使用 Django 进行设置非常容易。

A
Aniruddh Agarwal

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

1) 创建一个 custom management command,例如

python manage.py my_cool_command

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

这是一个简单的解决方案,不需要安装繁重的 AMQP 堆栈。但是,使用其他答案中提到的芹菜之类的东西有很多好处。特别是,使用 Celery 时,不必将应用程序逻辑分散到 crontab 文件中是一件好事。但是,cron 解决方案非常适合中小型应用程序,并且您不希望有很多外部依赖项。

编辑:

在更高版本的 Windows 中,Windows 8、Server 2012 及更高版本不推荐使用 at 命令。您可以将 schtasks.exe 用于相同的用途。

**** 更新 **** 这是 django doc 的新 link,用于编写自定义管理命令


这是一种无需外部服务而是仅使用正在运行的 django 框架进程的方法吗?
@Brian_Neal django_cron 应用程序。
请帮助我了解如何在每个月的最后一天使用 cron 在虚拟环境中运行管理命令。
@sergzach 我跟进了此评论,结果发现有两个具有此名称的包。 django-cron on Google Codedjango-cron on Github。它们略有不同,但都很有趣。两者都允许您以“Djangonic”的方式定义 crons。第一个有点老,旨在在没有外部任务(即 cron)的情况下工作。另一方面,第二个要求您设置一个 cron 来运行 python manage.py runcrons,然后运行您定义和注册的所有 cron。
@sergzach 我假设您指的是第一个,“Google Code 上的 django-cron”。你是对的。这实际上是为什么我选择第二个,“GitHub 上的 django-cron”,因为它使你有一个简单的 crontab 设置/管理 - 只有一个 crontab,指的是管理命令 - 但因为你使用的是单独的cron 进程可以避免这个同步问题(据我所知)。
W
WhyNotHugo

Celery 是一个分布式任务队列,建立在 AMQP (RabbitMQ) 之上。它还以类似 cron 的方式处理周期性任务(请参阅 periodic tasks)。根据您的应用程序,可能值得一试。

Celery 很容易用 django (docs) 设置,周期性任务实际上会在停机时跳过错过的任务。 Celery 还具有内置的重试机制,以防任务失败。


l
leonheess

我们已经开源了我认为的结构化应用程序。布赖恩的上述解决方案也暗示了这一点。我们会喜欢任何/所有反馈!

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

它带有一个管理命令:

./manage.py runcrons

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


@chachra 抱歉,我知道这可能是一个愚蠢的问题,但这是否可以通过 at 在 Windows 上运行,或者它是专门为与 cron 一起使用而设计的?
@BrunoFinger 它使用 python 类,所以它基本上只是 python,不需要特定于平台的命令。
x
xuhdev

如果您使用的是标准 POSIX 操作系统,则使用 cron

如果您使用的是 Windows,则使用 at

写一个 Django 管理命令到

弄清楚他们在哪个平台上。为您的用户执行适当的“AT”命令,或为您的用户更新 crontab。


如果可能的话,我希望将它汇总到我的 django 应用程序中。
@TM:“汇总到我的 django 应用程序中”是什么意思?请澄清你的问题。
我希望人们能够轻松部署此应用程序,而无需自己设置 cron 作业。
您始终可以将 cron 接口包装到您的应用程序中。
BSD、Mac 和任何类 Unix 操作系统都有 cron。
A
Austin Adams

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

您只需添加一个用作计时器的 cron 条目,并且您可以在脚本中运行一个非常好的 Django 管理界面。


django-chronograph 未维护。它的 fork 做得更好:github.com/chrisspen/django-chroniker
u
user41767

看看 Django Poor Man's Cron,这是一个 Django 应用程序,它利用垃圾邮件机器人、搜索引擎索引机器人等以大约固定的时间间隔运行计划任务

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


这还假设您的 Django 应用程序可以从 Web 访问,而 LAN 和 VPN 上的部署则不是这种情况。
P
PhoenixDev

前段时间我有完全相同的要求,最终使用 APScheduler (User Guide) 解决了它

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

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

希望这对某人有帮助!


你如何将它包含在 Django 应用程序中?您是否在 wsgi.py 中创建调度程序?或者这是作为一个完全独立的进程运行的?
嘿@PhoenixDev,我如何在 django 项目结构中使用它?我把这个调度器放在哪里?将不胜感激任何建议。
J
Johannes Gorset

Brian Neal 建议通过 cron 运行管理命令效果很好,但如果您正在寻找更强大的东西(但不像 Celery 那样精细),我会研究像 Kronos 这样的库:

# app/cron.py

import kronos

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

J
Jean-François Fabre

用于调度程序作业的 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

您可以通过执行 [点击这里] https://github.com/devchandansh/django-apscheduler 查看完整代码


s
sleblanc

RabbitMQ 和 Celery 比 Cron 有更多的特性和任务处理能力。如果任务失败不是问题,并且您认为您将在下一次调用中处理中断的任务,那么 Cron 就足够了。

芹菜AMQP 将让您处理损坏的任务,并且它将由另一个工作人员再次执行(Celery 工作人员监听下一个要处理的任务),直到达到任务的 max_retries 属性。您甚至可以在失败时调用任务,例如记录失败,或在到达 max_retries 后向管理员发送电子邮件。

当您需要扩展应用程序时,您可以分发 Celery 和 AMQP 服务器。


c
chhantyal

我个人使用 cron,但 django-extensionsJobs Scheduling 部分看起来很有趣。


仍然依赖 cron 来触发,只是在两者之间增加了另一个抽象层。不知道值不值得,就个人而言。
我同意,并且在考虑之后,我不希望请求中间件减慢我的网站(上面的ala Poormanscron),因为 cron 无论如何都可以更好地完成这项工作。
A
Alexander

虽然不是 Django 的一部分,但 Airflow 是一个更新的项目(截至 2016 年),它对任务管理很有用。

Airflow 是一个工作流自动化和调度系统,可用于创作和管理数据管道。基于 Web 的 UI 为开发人员提供了一系列用于管理和查看这些管道的选项。

Airflow 是用 Python 编写的,并使用 Flask 构建。

Airflow 由 Airbnb 的 Maxime Beauchemin 创建并于 2015 年春季开源。它于 2016 年冬季加入了 Apache 软件基金会的孵化计划。这里是Git project page和一些补充background information


M
Matt McCormick

将以下内容放在 cron.py 文件的顶部:

#!/usr/bin/python
import os, sys
sys.path.append('/path/to/') # the parent directory of the project
sys.path.append('/path/to/project') # these lines only needed if not on path
os.environ['DJANGO_SETTINGS_MODULE'] = 'myproj.settings'

# imports and code below

M
Michael

我只是想到了这个相当简单的解决方案:

定义一个视图函数 do_work(req, param) 就像使用任何其他视图一样,使用 URL 映射,返回一个 HttpResponse 等等。使用您的计时首选项(或在 Windows 中使用 AT 或计划任务)设置运行 curl http://localhost/your/mapped/url?param=value 的 cron 作业。

您可以添加参数,但只需将参数添加到 URL。

告诉我你们的想法。

[更新]我现在使用的是来自 django-extensions 的 runjob 命令,而不是 curl。

我的 cron 看起来像这样:

@hourly python /path/to/project/manage.py runjobs hourly

... 以此类推,适用于每日、每月等。您还可以将其设置为运行特定作业。

我发现它更易于管理和更清洁。不需要将 URL 映射到视图。只需定义您的工作类别和 crontab 即可。


我感觉到的唯一问题是不必要地增加了应用程序的负载和带宽,只是为了运行一个最好在“内部”启动并且独立于服务应用程序的后台作业。但除此之外,这是一个更聪明、更通用的 django-cron,因为它甚至可以被应用服务器外部的代理调用!
你是对的,这就是我转向使用 django-command-extensions 中的作业的原因。请参阅我对答案的更新。
x
xiaohei

在部分代码之后,我可以写任何东西,就像我的views.py :)

#######################################
import os,sys
sys.path.append('/home/administrator/development/store')
os.environ['DJANGO_SETTINGS_MODULE']='store.settings'
from django.core.management impor setup_environ
from store import settings
setup_environ(settings)
#######################################

来自http://www.cotellese.net/2007/09/27/running-external-scripts-against-django-models/


s
saran3h

你一定要看看 django-q!它不需要额外的配置,并且很可能拥有处理商业项目中任何生产问题所需的一切。

它正在积极开发并与 django、django ORM、mongo、redis 很好地集成。这是我的配置:

# django-q
# -------------------------------------------------------------------------
# See: http://django-q.readthedocs.io/en/latest/configure.html
Q_CLUSTER = {
    # Match recommended settings from docs.
    'name': 'DjangoORM',
    'workers': 4,
    'queue_limit': 50,
    'bulk': 10,
    'orm': 'default',

# Custom Settings
# ---------------
# Limit the amount of successful tasks saved to Django.
'save_limit': 10000,

# See https://github.com/Koed00/django-q/issues/110.
'catch_up': False,

# Number of seconds a worker can spend on a task before it's terminated.
'timeout': 60 * 5,

# Number of seconds a broker will wait for a cluster to finish a task before presenting it again. This needs to be
# longer than `timeout`, otherwise the same task will be processed multiple times.
'retry': 60 * 6,

# Whether to force all async() calls to be run with sync=True (making them synchronous).
'sync': False,

# Redirect worker exceptions directly to Sentry error reporter.
'error_reporter': {
    'sentry': RAVEN_CONFIG,
},
}

N
Ni Xiaoni

是的,上面的方法太棒了。我尝试了其中的一些。最后,我找到了这样的方法:

    from threading import Timer

    def sync():

        do something...

        sync_timer = Timer(self.interval, sync, ())
        sync_timer.start()

就像递归一样。

好的,我希望这个方法能满足你的要求。 :)


如果您的“某事”失败,将停止,因此请确保您处理其中的所有异常。即使这样,Web 服务器也可能会在某个时候杀死您的线程,不是吗?
d
devdrc

一个更现代的解决方案(与 Celery 相比)是 Django Q:https://django-q.readthedocs.io/en/latest/index.html

它有很好的文档并且很容易理解。缺少 Windows 支持,因为 Windows 不支持进程分叉。但是,如果您使用 Windows for Linux 子系统创建开发环境,它就可以正常工作。


您似乎可以在 Windows 上以单集群模式still use it
F
Fabricio Buzeto

我今天遇到了类似你的问题。

我不想让服务器通过 cron 处理它(大多数库最终只是 cron 助手)。

所以我创建了一个调度模块并将其附加到 init 。

这不是最好的方法,但它可以帮助我将所有代码放在一个地方,并且它的执行与主应用程序相关。


P
Peter Brittain

我使用 celery 来创建我的定期任务。首先,您需要按如下方式安装它:

pip install django-celery

不要忘记在您的设置中注册 django-celery,然后您可以执行以下操作:

from celery import task
from celery.decorators import periodic_task
from celery.task.schedules import crontab
from celery.utils.log import get_task_logger
@periodic_task(run_every=crontab(minute="0", hour="23"))
def do_every_midnight():
 #your code

我注意到这个建议已经过时了,你可以直接集成 celery。有关详细信息,请参阅 pypi.python.org/pypi/django-celery
Celery docs 说这是 v3.1 中的更改。我自己还没有尝试过。
j
just10minutes

我不确定这对任何人是否有用,因为我必须提供系统的其他用户来安排作业,而没有让他们访问实际的服务器(Windows)任务计划程序,我创建了这个可重用的应用程序。

请注意,用户可以访问服务器上的一个共享文件夹,他们可以在其中创建所需的命令/任务/.bat 文件。然后可以使用此应用程序安排此任务。

应用名称是 Django_Windows_Scheduler

https://i.stack.imgur.com/y3gtF.png


S
Sri

如果您想要比 Celery 更可靠的东西,请尝试构建在 AWS SQS/SNS 之上的 TaskHawk。

参考:http://taskhawk.readthedocs.io


y
yspreen

对于简单的 dockerized 项目,我真的看不出任何现有的答案合适。

所以我写了一个非常简单的解决方案,不需要外部库或触发器,它可以自己运行。不需要外部 os-cron,应该可以在每个环境中工作。

它通过添加中间件来工作:middleware.py

import threading

def should_run(name, seconds_interval):
    from application.models import CronJob
    from django.utils.timezone import now

    try:
        c = CronJob.objects.get(name=name)
    except CronJob.DoesNotExist:
        CronJob(name=name, last_ran=now()).save()
        return True

    if (now() - c.last_ran).total_seconds() >= seconds_interval:
        c.last_ran = now()
        c.save()
        return True

    return False


class CronTask:
    def __init__(self, name, seconds_interval, function):
        self.name = name
        self.seconds_interval = seconds_interval
        self.function = function


def cron_worker(*_):
    if not should_run("main", 60):
        return

    # customize this part:
    from application.models import Event
    tasks = [
        CronTask("events", 60 * 30, Event.clean_stale_objects),
        # ...
    ]

    for task in tasks:
        if should_run(task.name, task.seconds_interval):
            task.function()


def cron_middleware(get_response):

    def middleware(request):
        response = get_response(request)
        threading.Thread(target=cron_worker).start()
        return response

    return middleware

models/cron.py

from django.db import models


class CronJob(models.Model):
    name = models.CharField(max_length=10, primary_key=True)
    last_ran = models.DateTimeField()

settings.py

MIDDLEWARE = [
    ...
    'application.middleware.cron_middleware',
    ...
]

H
Hamfri

简单的方法是编写自定义 shell 命令参见 Django Documentation 并在 linux 上使用 cronjob 执行它。但是我强烈推荐使用像 RabbitMQ 这样的消息代理和 celery。也许你可以看看这个Tutorial


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅