Django - настроить запланированное задание?

464

Я работаю над веб-приложением, используя Django, и мне любопытно, есть ли способ запланировать выполнение задания периодически.

В основном я просто хочу запускать базу данных и делать некоторые вычисления/обновления на регулярной основе, но я не могу найти никакой документации по этому поводу.

Кто-нибудь знает, как настроить это?

Чтобы уточнить: я знаю, что могу настроить для этого задание cron, но мне любопытно, есть ли какая-то функция в Django, которая предоставляет эту функциональность. Я бы хотел, чтобы люди могли самостоятельно развертывать это приложение, не выполняя много конфигураций (предпочтительно нуль).

Я рассмотрел запуск этих действий "задним числом", просто проверяя, должно ли выполняться задание с момента последнего запроса запроса на сайт, но я надеюсь на что-то более чистое.

  • 1
    Если вы высокопроизводительный сайт и уже используете RabbitMQ, вот хитрость, чтобы обойти cron: Использование AMQP для выполнения cron-like планирования
  • 0
    Если я правильно понимаю, вам нужно запланировать некоторые задачи в Django. Лучшее, что я нахожу в эти дни, это: celery.github.com/celery/index.html
Показать ещё 3 комментария
Теги:
web-applications
scheduled-tasks

22 ответа

337
Лучший ответ

Одним из решений, которое я использовал, является следующее:

1) Создайте команду пользовательское управление, например.

python manage.py my_cool_command

2) Используйте cron (в Linux) или at (в Windows) для запуска моей команды в требуемые моменты времени.

Это простое решение, которое не требует установки тяжелого стека AMQP. Однако есть хорошие преимущества в использовании чего-то типа сельдерея, упомянутого в других ответах. В частности, с Celery неплохо не распространять логику приложения в файлы crontab. Однако решение cron работает довольно хорошо для приложения малого и среднего размера и где вы не хотите много внешних зависимостей.

EDIT:

В более поздней версии окон команда at устарела для Windows 8, Server 2012 и выше. Вы можете использовать schtasks.exe для такого же использования.

  • 4
    Это способ сделать это без внешних сервисов, но используя только запущенный процесс фреймворка django?
  • 4
    Приложение @Brian_Neal django_cron.
Показать ещё 7 комментариев
119

Celery - это распределенная очередь задач, построенная на AMQP (RabbitMQ). Он также обрабатывает периодические задачи с помощью cron-like (см. периодические задачи). В зависимости от вашего приложения это может стоить gander.

Сельдерей довольно легко настроить с помощью django (docs), а периодические задачи фактически пропустят пропущенные задачи в случае простоя, Сельдерей также имеет встроенные механизмы повтора, в случае неудачи задачи.

46

У нас есть open-source, что я считаю структурированным приложением. что решение Брайана выше намека. Хотелось бы любить любую/всю обратную связь!

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

Он поставляется с одной командой управления:

./manage.py runcrons

Это делает работу. Каждый cron моделируется как класс (поэтому его все OO), и каждый cron работает на другой частоте, и мы убеждаемся, что один и тот же тип cron не работает параллельно (в случае, если сами кроны занимают больше времени, чем их частота!)

Спасибо!

  • 3
    @chachra Извините, я знаю, что это может быть глупый вопрос, но будет ли это работать на windows через at или было разработано специально для работы с cron ?
33

Если вы используете стандартную ОС POSIX, вы используете cron.

Если вы используете Windows, вы используете в.

Напишите команду управления Django для

  • Определите, на какой платформе они находятся.

  • Либо выполните соответствующую команду "AT" для ваших пользователей, или обновите crontab для своих пользователей.

  • 9
    Я хотел бы свернуть его в мое приложение Django, если это возможно.
  • 0
    @TM: Что означает «свернутый в мое приложение django»? Пожалуйста, уточните свой вопрос.
Показать ещё 4 комментария
24

Интересное новое подключаемое приложение Django: django-chronograph

Вам нужно добавить только одну запись cron, которая действует как таймер, и у вас есть очень приятный интерфейс администратора Django для запуска скриптов.

  • 0
    Этот пакет не обслуживался, и его было так много.
14

Посмотрите на Django Poor Man Cron, который является приложением Django, в котором используются спам-боты, роботы для индексирования поисковых систем и одинаковые для регулярного выполнения запланированных задач.

Смотрите: http://code.google.com/p/django-poormanscron/

  • 1
    Это также предполагает, что ваше приложение Django доступно из Интернета, что не относится к развертываниям в локальных и виртуальных сетях.
9

RabbitMQ и Celery имеют больше возможностей и возможностей обработки задач, чем Cron. Если сбой задачи не является проблемой, и вы считаете, что будете обрабатывать сломанные задачи при следующем вызове, тогда Cron будет достаточным.

Сельдерей и AMQP позволит вам справиться с нарушенной задачей, и он снова будет выполнен другим работником (работники Celery послушают следующую задачу для работы), пока не будет достигнут атрибут задачи max_retries. Вы можете даже вызывать задачи при сбое, например, регистрировать ошибку или отправлять электронное письмо администратору после достижения max_retries.

И вы можете распространять серверы сельдерея и AMQP, когда вам нужно масштабировать свое приложение.

9

Предложение Брайана Нила о выполнении управляющих команд через cron работает хорошо, но если вы ищете что-то немного более надежное (но не такое сложное, как Celery), я бы заглянул в библиотеку вроде Kronos:

# app/cron.py

import kronos

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

Я лично использую cron, но Планирование работ частей django-extensions выглядит интересным.

  • 0
    Все еще зависит от cron для запуска, просто добавляет еще один уровень абстракции между ними. Не уверен, что оно того стоит, лично.
  • 0
    Я согласен, и, подумав об этом, я не хочу, чтобы промежуточное программное обеспечение замедляло работу моего сайта (аля бедняжка выше), когда cron все равно может сделать эту работу лучше.
6

У меня было точно такое же требование некоторое время назад, и я решил его решить с помощью 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

Надеюсь, это поможет кому-то!

  • 0
    Это точно помогло мне ^ _ ^ Спасибо
6

Хотя он не является частью Django, Airflow - это более новый проект (начиная с 2016 года), который полезен для управления задачами.

Airflow - это система автоматизации и планирования рабочего процесса, которая может использоваться для создания и управления конвейерами данных. Веб-интерфейс пользователя предоставляет разработчику ряд опций для управления и просмотра этих конвейеров.

Воздушный поток написан на Python и построен с использованием Flask.

Airflow был создан Maxime Beauchemin в Airbnb и открыт в spring 2015 года. Он присоединился к инкубационной программе Apache Software Foundations зимой 2016 года. Здесь Git страница проекта и дополнительная информация справочная информация.

6

Я просто подумал об этом довольно простом решении:

  1. Определите функцию представления do_work (req, param), как и с любым другим видом, с отображением URL-адресов, возвратом HttpResponse и т.д.
  2. Настройте задание cron с вашими настройками времени (или с помощью AT или запланированных задач в Windows), в котором выполняется завиток http://localhost/your/mapped/url? Param = value.

Вы можете добавлять параметры, а просто добавлять параметры к URL.

Расскажите мне, что вы, ребята, думаете.

[Обновить] Теперь я использую команду runjob из django-extensions вместо curl.

Мой cron выглядит примерно так:

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

... и т.д. для ежедневных, ежемесячных и т.д. ". Вы также можете настроить его для выполнения определенного задания.

Я нахожу его более управляемым и чище. Не требует сопоставления URL-адреса для представления. Просто определите свой класс работы и crontab, и вы настроены.

  • 1
    Единственная проблема, которую я чувствую, - это необязательно добавление нагрузки к приложению и пропускной способности, чтобы запустить фоновое задание, которое лучше запускать «внутри» и независимо от обслуживающего приложения. Но кроме этого, это умный и более общий django-cron, потому что он может даже вызываться агентами, внешними по отношению к серверу приложения!
  • 0
    Вы правы, поэтому я перешел на использование заданий из django-command-extensions. Смотрите мое обновление к моему ответу.
6

Поместите следующее в начало файла 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
4

после части кода я могу написать все, что угодно, как my 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/

2

Вы должны обязательно проверить 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 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,
},
}
2

Да, метод выше настолько велик. И я попробовал некоторые из них. Наконец, я нашел такой метод:

    from threading import Timer

    def sync():

        do something...

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

Также как Рекурсивный.

Хорошо, я надеюсь, что этот метод может удовлетворить ваши требования.:)

  • 1
    Остановится, если ваше «что-то» потерпит неудачу, поэтому убедитесь, что вы обрабатываете все исключения внутри него. Даже тогда, веб-сервер может в какой-то момент убить ваш поток, не так ли?
2

Сегодня у меня было что-то похожее на вашу проблему.

Я не хотел, чтобы он обрабатывался сервером trhough cron (и большинство из них были просто помощниками cron в конце).

Итак, я создал модуль планирования и привязал его к init.

Это не лучший подход, но он помогает мне иметь весь код в одном месте и с его исполнением, связанным с основным приложением.

1

Более современное решение (по сравнению с сельдереем) - это Django Q: https://django-q.readthedocs.io/en/latest/index.html

У него отличная документация, и он легко разбирается. Отсутствует поддержка Windows, поскольку Windows не поддерживает процесс форсинга. Но он отлично работает, если вы создаете среду разработки с помощью подсистемы Windows для Linux.

1

Я не уверен, что это будет полезно для всех, поскольку я должен был предоставить другим пользователям системы расписание заданий, не предоставляя им доступ к фактическому планировщику планировщика (Windows), я создал это многоразовое приложение.

Обратите внимание, что у пользователей есть доступ к одной общей папке на сервере, где они могут создавать требуемый файл command/task/.bat. Затем эту задачу можно планировать с помощью этого приложения.

Имя приложения Django_Windows_Scheduler

ScreenShot: Изображение 911

1

Я использую сельдерей для создания своих периодических задач. Сначала вам нужно установить его следующим образом:

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
  • 2
    Я заметил, что этот совет устарел, и вы можете интегрировать сельдерей напрямую. Смотрите pypi.python.org/pypi/django-celery для подробностей.
  • 1
    : o круто, с какой версии можно это сделать?
Показать ещё 1 комментарий
0

Для простых докеризованных проектов я не мог найти подходящий ответ.

Поэтому я написал очень скромное решение без необходимости использования внешних библиотек или триггеров, которое работает само по себе. Не требуется внешний os-cron, он должен работать в любой среде.

Это работает путем добавления промежуточного middleware.py обеспечения: 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',
    ...
]
0

Если вы хотите что-то более надежное, чем Celery, попробуйте TaskHawk, который построен поверх AWS SQS/SNS.

См. Http://taskhawk.readthedocs.io

Ещё вопросы

Сообщество Overcoder
Наверх
Меню