Я работаю над веб-приложением, используя Django, и мне любопытно, есть ли способ запланировать выполнение задания периодически.
В основном я просто хочу запускать базу данных и делать некоторые вычисления/обновления на регулярной основе, но я не могу найти никакой документации по этому поводу.
Кто-нибудь знает, как настроить это?
Чтобы уточнить: я знаю, что могу настроить для этого задание cron
, но мне любопытно, есть ли какая-то функция в Django, которая предоставляет эту функциональность. Я бы хотел, чтобы люди могли самостоятельно развертывать это приложение, не выполняя много конфигураций (предпочтительно нуль).
Я рассмотрел запуск этих действий "задним числом", просто проверяя, должно ли выполняться задание с момента последнего запроса запроса на сайт, но я надеюсь на что-то более чистое.
Одним из решений, которое я использовал, является следующее:
1) Создайте команду пользовательское управление, например.
python manage.py my_cool_command
2) Используйте cron
(в Linux) или at
(в Windows) для запуска моей команды в требуемые моменты времени.
Это простое решение, которое не требует установки тяжелого стека AMQP. Однако есть хорошие преимущества в использовании чего-то типа сельдерея, упомянутого в других ответах. В частности, с Celery неплохо не распространять логику приложения в файлы crontab. Однако решение cron работает довольно хорошо для приложения малого и среднего размера и где вы не хотите много внешних зависимостей.
EDIT:
В более поздней версии окон команда at
устарела для Windows 8, Server 2012 и выше. Вы можете использовать schtasks.exe
для такого же использования.
Celery - это распределенная очередь задач, построенная на AMQP (RabbitMQ). Он также обрабатывает периодические задачи с помощью cron-like (см. периодические задачи). В зависимости от вашего приложения это может стоить gander.
Сельдерей довольно легко настроить с помощью django (docs), а периодические задачи фактически пропустят пропущенные задачи в случае простоя, Сельдерей также имеет встроенные механизмы повтора, в случае неудачи задачи.
У нас есть open-source, что я считаю структурированным приложением. что решение Брайана выше намека. Хотелось бы любить любую/всю обратную связь!
https://github.com/tivix/django-cron
Он поставляется с одной командой управления:
./manage.py runcrons
Это делает работу. Каждый cron моделируется как класс (поэтому его все OO), и каждый cron работает на другой частоте, и мы убеждаемся, что один и тот же тип cron не работает параллельно (в случае, если сами кроны занимают больше времени, чем их частота!)
Спасибо!
at
или было разработано специально для работы с cron
?
Если вы используете стандартную ОС POSIX, вы используете cron.
Если вы используете Windows, вы используете в.
Напишите команду управления Django для
Определите, на какой платформе они находятся.
Либо выполните соответствующую команду "AT" для ваших пользователей, или обновите crontab для своих пользователей.
Интересное новое подключаемое приложение Django: django-chronograph
Вам нужно добавить только одну запись cron, которая действует как таймер, и у вас есть очень приятный интерфейс администратора Django для запуска скриптов.
Посмотрите на Django Poor Man Cron, который является приложением Django, в котором используются спам-боты, роботы для индексирования поисковых систем и одинаковые для регулярного выполнения запланированных задач.
RabbitMQ и Celery имеют больше возможностей и возможностей обработки задач, чем Cron. Если сбой задачи не является проблемой, и вы считаете, что будете обрабатывать сломанные задачи при следующем вызове, тогда Cron будет достаточным.
Сельдерей и AMQP позволит вам справиться с нарушенной задачей, и он снова будет выполнен другим работником (работники Celery послушают следующую задачу для работы), пока не будет достигнут атрибут задачи max_retries
. Вы можете даже вызывать задачи при сбое, например, регистрировать ошибку или отправлять электронное письмо администратору после достижения max_retries
.
И вы можете распространять серверы сельдерея и AMQP, когда вам нужно масштабировать свое приложение.
Предложение Брайана Нила о выполнении управляющих команд через cron работает хорошо, но если вы ищете что-то немного более надежное (но не такое сложное, как Celery), я бы заглянул в библиотеку вроде Kronos:
# app/cron.py
import kronos
@kronos.register('0 * * * *')
def task():
pass
Я лично использую cron, но Планирование работ частей django-extensions выглядит интересным.
У меня было точно такое же требование некоторое время назад, и я решил его решить с помощью 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, Airflow - это более новый проект (начиная с 2016 года), который полезен для управления задачами.
Airflow - это система автоматизации и планирования рабочего процесса, которая может использоваться для создания и управления конвейерами данных. Веб-интерфейс пользователя предоставляет разработчику ряд опций для управления и просмотра этих конвейеров.
Воздушный поток написан на Python и построен с использованием Flask.
Airflow был создан Maxime Beauchemin в Airbnb и открыт в spring 2015 года. Он присоединился к инкубационной программе Apache Software Foundations зимой 2016 года. Здесь Git страница проекта и дополнительная информация справочная информация.
Я просто подумал об этом довольно простом решении:
Вы можете добавлять параметры, а просто добавлять параметры к URL.
Расскажите мне, что вы, ребята, думаете.
[Обновить] Теперь я использую команду runjob из django-extensions вместо curl.
Мой cron выглядит примерно так:
@hourly python /path/to/project/manage.py runjobs hourly
... и т.д. для ежедневных, ежемесячных и т.д. ". Вы также можете настроить его для выполнения определенного задания.
Я нахожу его более управляемым и чище. Не требует сопоставления URL-адреса для представления. Просто определите свой класс работы и crontab, и вы настроены.
Поместите следующее в начало файла 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
после части кода я могу написать все, что угодно, как 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/
Вы должны обязательно проверить 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,
},
}
Да, метод выше настолько велик. И я попробовал некоторые из них. Наконец, я нашел такой метод:
from threading import Timer
def sync():
do something...
sync_timer = Timer(self.interval, sync, ())
sync_timer.start()
Также как Рекурсивный.
Хорошо, я надеюсь, что этот метод может удовлетворить ваши требования.:)
Сегодня у меня было что-то похожее на вашу проблему.
Я не хотел, чтобы он обрабатывался сервером trhough cron (и большинство из них были просто помощниками cron в конце).
Итак, я создал модуль планирования и привязал его к init.
Это не лучший подход, но он помогает мне иметь весь код в одном месте и с его исполнением, связанным с основным приложением.
Более современное решение (по сравнению с сельдереем) - это Django Q: https://django-q.readthedocs.io/en/latest/index.html
У него отличная документация, и он легко разбирается. Отсутствует поддержка Windows, поскольку Windows не поддерживает процесс форсинга. Но он отлично работает, если вы создаете среду разработки с помощью подсистемы Windows для Linux.
Я не уверен, что это будет полезно для всех, поскольку я должен был предоставить другим пользователям системы расписание заданий, не предоставляя им доступ к фактическому планировщику планировщика (Windows), я создал это многоразовое приложение.
Обратите внимание, что у пользователей есть доступ к одной общей папке на сервере, где они могут создавать требуемый файл command/task/.bat. Затем эту задачу можно планировать с помощью этого приложения.
Имя приложения Django_Windows_Scheduler
ScreenShot:
Я использую сельдерей для создания своих периодических задач. Сначала вам нужно установить его следующим образом:
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
Для простых докеризованных проектов я не мог найти подходящий ответ.
Поэтому я написал очень скромное решение без необходимости использования внешних библиотек или триггеров, которое работает само по себе. Не требуется внешний 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',
...
]
Если вы хотите что-то более надежное, чем Celery, попробуйте TaskHawk, который построен поверх AWS SQS/SNS.