Python 设置计划作业?

Python 设置计划作业?,python,django,web-applications,scheduled-tasks,Python,Django,Web Applications,Scheduled Tasks,我一直在使用Django开发一个web应用程序,我很好奇是否有办法安排一个作业定期运行 基本上,我只想运行数据库,并自动、定期地进行一些计算/更新,但我似乎找不到任何关于这样做的文档 有人知道怎么设置吗 澄清一下:我知道我可以设置一个cron作业来完成这项工作,但我很好奇Django中是否有提供此功能的功能。我希望人们能够自己部署这个应用程序,而不必做很多配置(最好是零配置) 我曾考虑过通过简单地检查自上次向站点发送请求以来是否应该运行作业来“追溯”触发这些操作,但我希望有更干净的东西。如果您使

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

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

有人知道怎么设置吗


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


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

如果您使用的是标准POSIX操作系统,您可以使用

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

将Django管理命令写入

  • 弄清楚他们在哪个平台上

  • 为用户执行适当的“AT”命令,或为用户更新crontab


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

    1) 创建一个

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

    这是一个简单的解决方案,不需要安装沉重的AMQP堆栈。然而,在其他答案中提到,使用芹菜这样的东西有很多好处。特别是,对于芹菜,不必将应用程序逻辑分散到crontab文件中是很好的。然而,cron解决方案非常适合中小型应用程序,并且您不需要太多的外部依赖性

    编辑:

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

    ****更新****
    这是django doc编写自定义管理命令的新版本

    看看django Poor Man's Cron,这是一款django应用程序,它利用Spambot、搜索引擎索引机器人等工具,以大约定期的时间间隔运行计划任务


    请参阅:

    我个人使用cron,但其部分看起来很有趣。

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

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

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


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

    将以下内容放在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
    

    完成部分代码后,我可以编写任何类似于我的视图的内容。py:)


    我今天对你的问题也有类似的看法

    我不想让服务器trhough cron来处理它(大多数lib最终只是cron助手)

    因此,我创建了一个调度模块并将其附加到init


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

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

  • 定义一个视图函数do_work(req,param)就像处理任何其他视图一样,使用URL映射,返回一个HttpResponse等等
  • 使用计时首选项(或使用AT或Windows中的计划任务)设置运行curl的cron作业
  • 您可以添加参数,但只需将参数添加到URL即可

    告诉我你们的想法

    [Update]我现在使用的是来自的runjob命令,而不是curl命令

    我的cron看起来像这样:

    @hourly python /path/to/project/manage.py runjobs hourly
    
        from threading import Timer
    
        def sync():
    
            do something...
    
            sync_timer = Timer(self.interval, sync, ())
            sync_timer.start()
    
    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
    
    。。。每天、每月等等。您还可以将其设置为运行特定作业


    我发现它更容易管理,更干净。不需要将URL映射到视图。只需定义您的作业类和crontab,就可以了。

    Brian Neal关于通过cron运行管理命令的建议效果很好,但如果您正在寻找更健壮(但没有芹菜那么精致)的工具,我会研究如下库:


    我们已经开源了我认为是结构化的应用程序。上面布赖恩的解决方案也暗示了这一点。我们希望得到任何/所有反馈

    它附带一个管理命令:

    ./manage.py runcrons
    

    那就行了。每个cron都被建模为一个类(因此它都是面向对象的),每个cron以不同的频率运行,我们确保相同的cron类型不会并行运行(以防cron自身运行的时间比其频率长!)

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

    Celery&将允许您处理中断的任务,并且它将由另一个工作人员再次执行(Celery工作人员侦听下一个要处理的任务),直到达到任务的
    max_retries
    属性。您甚至可以在出现故障时调用任务,例如记录故障,或者在达到
    max\u retries
    后向管理员发送电子邮件


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

    是的,上述方法非常好。我试了一些。最后,我找到了这样一种方法:

    @hourly python /path/to/project/manage.py runjobs hourly
    
        from threading import Timer
    
        def sync():
    
            do something...
    
            sync_timer = Timer(self.interval, sync, ())
            sync_timer.start()
    
    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
    
    就像递归一样


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

    我用芹菜做定期任务。首先,您需要按如下方式安装它:

    pip install django-celery
    
    别忘了在你的设置中注册
    django芹菜
    ,然后你就可以这样做了
    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-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,
    },
    }
    
    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
    
    from django.db import models
    
    
    class CronJob(models.Model):
        name = models.CharField(max_length=10, primary_key=True)
        last_ran = models.DateTimeField()
    
    MIDDLEWARE = [
        ...
        'application.middleware.cron_middleware',
        ...
    ]
    
    pip install apscheduler
    
    def FirstCronTest():
        print("")
        print("I am executed..!")
    
    from apscheduler.schedulers.background import BackgroundScheduler
    scheduler = BackgroundScheduler()
    
    import scheduler_jobs 
    
    scheduler.add_job(scheduler_jobs.FirstCronTest, 'interval', seconds=10)
    scheduler.start()
    
    import execute