Налаштувати заплановану роботу?


519

Я працюю над веб-додатком за допомогою Django, і мені цікаво, чи є спосіб запланувати роботу, яку потрібно періодично запускати.

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

Хтось знає, як це налаштувати?

Для уточнення: я знаю, що я можу налаштувати cronроботу для цього, але мені цікаво, чи є в Django якась особливість, яка забезпечує цю функціональність. Я хотів би, щоб люди могли самостійно розгортати цю програму без необхідності робити багато конфігурацій (бажано нульових).

Я розглядаю можливість запускати ці дії "заднім числом", просто перевіряючи, чи потрібно було виконати роботу з моменту останнього надсилання запиту на сайт, але я сподіваюся на щось чистіше.


1
Якщо ви є високоефективним сайтом і вже використовуєте RabbitMQ, ось ось фокус, щоб обійти cron: Використання AMQP для здійснення планування подібного крон
Van Gale

Якщо я правильно розумію, вам потрібно запланувати деякі завдання в Джанго. Найкраще, що я вважаю сьогодні: це: celery.github.com/celery/index.html
Алі Нікшешан

що ти думаєш про це? github.com/reavis/django-cron
Доменіко Монако

Поставити галочку хоч просто, щоб уникнути вас усієї цієї роботи. [Відмова] Я будую галочку.
Siscia

2
Тут потрібно згадати github.com/coleifer/huey Huey. Це смішно просто налаштувати з Django.
Брендон Бертельсен

Відповіді:


363

Одне з моїх рішень - це зробити:

1) Створіть власну команду управління , наприклад

python manage.py my_cool_command

2) Використовуйте cron(в Linux) або at(в Windows), щоб запустити мою команду в необхідний час.

Це просте рішення, яке не потребує встановлення важкого стеку AMQP. Однак є приємні переваги використання чогось на кшталт селери, згаданого в інших відповідях. Зокрема, із селерою приємно не поширювати логіку програми у файли crontab. Однак рішення cron працює досить непогано для невеликого та середнього розміру додатків і там, де вам не потрібно багато зовнішніх залежностей.

Редагувати:

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

**** ОНОВЛЕННЯ **** Це нове посилання django doc для написання користувацької команди управління


5
Це спосіб зробити це без зовнішніх служб, але за допомогою єдиного запущеного рамкового процесу django?
sergzach

4
@Brian_Neal django_cron.
sergzach

2
Будь ласка, допоможіть мені зрозуміти, як я запускаю команду управління у віртуальному середовищі, використовуючи cron в останній день кожного місяця.
mmrs151

2
@sergzach Я продовжив цей коментар, і виявилося, що є два пакети з такою назвою. Джанго-Хроні на Google Code і Джанго-Хроні на Github . Вони трохи різні, але обидва цікаві. Обидва дозволяють визначати крони "Djangonic" способом. Перший - трохи старший і має на меті працювати без зовнішнього завдання (тобто крона). Друга сторона вимагає від вас встановити крон, python manage.py runcronsякий запускає всі визначені вами і зареєстровані крони.
driftcatcher

1
@sergzach Я припускаю, що ви посилаєтесь на першу, "django-cron у коді Google". Ви маєте рацію щодо цього. Це насправді, тому я вибираю другий, "django-cron на GitHub", тому що це робить так, щоб у вас було просте налаштування / управління crontab - лише один crontab, посилаючись на команду управління - але оскільки ви використовуєте окремий cron процес ви уникаєте цієї проблеми синхронізації (наскільки я можу сказати).
driftcatcher

152

Селера - це розподілена черга завдань, побудована на AMQP (RabbitMQ). Він також обробляє періодичні завдання кроноподібно (див. Періодичні завдання ). Залежно від вашої програми, можливо, варто попроситись.

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


51

Ми відкрили джерело того, що, на мою думку, є структурованим додатком. що рішення Брайана теж натякає. Ми б хотіли будь-які відгуки!

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

Він постачається з однією командою управління:

./manage.py runcrons

Це робить роботу. Кожен крон моделюється як клас (тому його все OO), і кожен cron працює з різною частотою, і ми переконаймося, що той самий тип крона не працює паралельно (у випадку, якщо самі крони запускають більше часу, ніж їх частота!)


5
@chachra Вибачте, я знаю, що це може бути тупим питанням, але чи буде це працювати на Windows через atабо це було розроблено спеціально для роботи cron?
Бруно Фінгер

38

Якщо ви використовуєте стандартну POSIX OS, ви використовуєте cron .

Якщо ви використовуєте Windows, ви використовуєте в .

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

  1. З’ясуйте, на якій платформі вони знаходяться.

  2. Або виконайте відповідну команду "AT" для своїх користувачів, або оновіть crontab для своїх користувачів.


10
Я хотів би, щоб це було згорнуто в мою програму джанго, якщо це можливо.
ТМ.

@TM: Що означає "згорнувшись у додаток для джанго"? Будь ласка, уточнюйте своє запитання.
S.Lott

10
Я хотів би, щоб люди могли легко розгортати цю програму без необхідності самостійно налаштовувати завдання cron.
ТМ.

1
Ви завжди можете зафіксувати інтерфейс cron у своєму додатку.
monkut

BSD, Mac та будь-яка ОС, схожа на Unix, мають cron.
DylanYoung

23

Цікавий новий підключається додаток Django: django-chronograph

Вам потрібно лише додати один запис крона, який працює як таймер, і у вас є дуже гарний інтерфейс адміністратора Django в сценарії для запуску.


2
джанго-хронограф не збережений. Це вила робить набагато краще: github.com/chrisspen/django-chroniker
Menda

16

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

Дивіться: http://code.google.com/p/django-poormanscron/


2
Це також передбачає, що ваш додаток Django доступний з Інтернету, що не стосується розгортання в локальних мережах та VPN.
TimH - Кодидакт

10

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

Сподіваюся, це комусь допоможе!


9

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

# app/cron.py

import kronos

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

9

RabbitMQ та Celery мають більше можливостей та можливостей у виконанні завдань, ніж Cron. Якщо невиконання завдання не є проблемою, і ви думаєте, що ви будете працювати з зламаними завданнями в наступному дзвінку, тоді Cron достатній.

Селера та AMQP дозволять вам впоратися з розбитою задачею, і її знову виконає інший працівник (працівники селери слухають наступне завдання над роботою), поки не max_retriesбуде досягнуто атрибут завдання . Ви навіть можете викликати завдання при відмові, як, наприклад, реєстрація помилки або надсилання електронного листа адміністраторуmax_retries буде досягнуто.

І ви можете розповсюджувати сервери Celery та AMQP, коли потрібно масштабувати свою програму.


8

Я особисто використовую cron, але для планування робочих місць частини розширень django виглядає цікаво.


Все ще залежить від крону для запуску, просто додає ще один абстракційний шар між ними. Не впевнений, чи варто того особисто.
Карл Мейєр

Я погоджуюсь, і, думаючи про це, я не хочу, щоб запит на проміжне програмне забезпечення сповільнював мій сайт (ala badmanscron вище), коли cron в будь-якому разі зможе зробити цю роботу краще.
Van Gale

7

Хоча не є частиною Django, Airflow - це останній проект (станом на 2016 рік), який корисний для управління завданнями.

Потік повітря - система автоматизації робочого процесу та планування, яка може бути використана для написання та управління трубопроводами даних. Веб-інтерфейс надає розробнику цілий ряд варіантів управління та перегляду цих конвеєрів.

Потік повітря написаний на Python і побудований за допомогою Flask.

Потік повітря був створений Maxime Beauchemin в Airbnb і відкрився джерелом навесні 2015 року. Він приєднався до програми інкубації Apache Software Foundation взимку 2016 року. Ось сторінка проекту Git та додаткова додаткова довідкова інформація .


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

6

Я просто думав про це досить просте рішення:

  1. Визначте функцію перегляду do_work (req, param), як і будь-який інший вид, з картографічним відображенням URL-адреси, поверніть HttpResponse тощо.
  2. Налаштування хрон з вашими уподобаннями синхронізації (або з допомогою AT або Призначені завдання в Windows) , який біжить локон HTTP: // локальний / ваш / зіставляються / URL = значення парам .

Ви можете додавати параметри, але лише додаючи параметри до URL-адреси.

Скажи мені, що ти думаєш

[Оновлення] Зараз я використовую команду runjob з розширень django замість curl.

Мій крон виглядає приблизно так:

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

... і так далі щодня, щомісяця тощо ". Ви також можете налаштувати його для виконання певної роботи.

Я вважаю це більш керованим та чистішим. Не потрібно відображати URL-адресу для подання. Просто визначте свій клас роботи та crontab, і ви налаштовані.


1
Єдина проблема, яку я відчуваю - це необов'язково додавати навантаження на додаток і пропускну здатність просто для запуску фонового завдання, яке краще запускати "внутрішньо" та незалежно від обслуговуючого додатка. Але крім цього, це розумний n більш загальний django-cron, оскільки його навіть можуть викликати агенти, зовнішні на сервері програми!
nemesisfixx

Ви маєте рацію, тому я перейшов до використання завдань із розширень django-command. Дивіться моє оновлення моєї відповіді.
Майкл

4

після частини коду я можу написати що завгодно, як і мій погляд.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/


3

Ви обов'язково повинні перевірити 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,
},
}

3

Джанго APScheduler для робіт із планування. Розширений планувальник Python (APScheduler) - це бібліотека Python, яка дозволяє планувати ваш код Python, який буде виконаний пізніше, один раз або періодично. Ви можете додавати нові завдання або видаляти старі на ходу як завгодно.

Примітка: Я автор цієї бібліотеки

Встановіть APScheduler

pip install apscheduler

Переглянути функцію файлу для дзвінка

ім'я файлу: rasporeder_jobs.py

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

Налаштування планувальника

зробіть файл Execute.py та додайте наведені нижче коди

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

Ваші письмові функції Тут функції планувальника записуються в planer_jobs

import scheduler_jobs 

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

Зв’яжіть файл для виконання

Тепер додайте нижній рядок у нижній частині файлу Url

import execute

2

У мене сьогодні було щось подібне з вашою проблемою.

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

Отже, я створив модуль планування і приєднав його до init .

Це не найкращий підхід, але він допомагає мені мати весь код в одному місці і з його виконанням пов'язаний з основним додатком.


2

Так, вищевказаний метод настільки чудовий. І я спробував деякі з них. Нарешті я знайшов такий метод:

    from threading import Timer

    def sync():

        do something...

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

Так само, як і рекурсивний .

Гаразд, я сподіваюся, що цей метод може відповідати вашим вимогам. :)


1
Припиниться, якщо ваше "щось" колись вийде з ладу, тому переконайтеся, що ви обробляєте всі винятки в ньому. Навіть тоді веб-сервер в якийсь момент може вбити вашу нитку, чи не так?
Lutz Prechelt

2

Більш сучасне рішення (порівняно з селерою) - Django Q: https://django-q.readthedocs.io/en/latest/index.html

Він має чудову документацію і легко поводитись. Підтримка Windows відсутня, оскільки Windows не підтримує розгортання процесу. Але це добре працює, якщо ви створюєте розроблювальне середовище за допомогою підсистеми Windows для Linux.



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 .
Пітер Брітайн

Документи із селери заявляють, що це було зміною версії 3.1. Я сам ще цього не пробував.
Пітер Брітайн

1

Я не впевнений, чи стане це корисним для когось, оскільки мені довелося надати іншим користувачам системи для планування завдань, не надаючи їм доступу до фактичного планувача завдань сервера (windows), я створив цю програму для багаторазового використання.

Зверніть увагу, що користувачі мають доступ до однієї спільної папки на сервері, де вони можуть створити необхідний файл команди / завдання / .bat. Це завдання потім можна запланувати за допомогою цієї програми.

Назва програми - Django_Windows_Scheduler

Екран екрану: введіть тут опис зображення



0

Для простих докерізованих проектів я не могла реально побачити відповідні відповіді.

Тож я написав дуже безпроблемне рішення, не потребуючи зовнішніх бібліотек чи тригерів, яке працює самостійно. Жоден зовнішній ос-крон не потрібен, він повинен працювати в будь-яких умовах.

Він працює, додаючи проміжне програмне забезпечення: 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

Простий спосіб - написати спеціальну команду оболонки, див. Документацію Django та виконати її за допомогою cronjob на Linux. Однак я б дуже рекомендував використовувати брокера повідомлень на зразок RabbitMQ у поєднанні з селерою. Можливо, ви можете поглянути на цей Підручник

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.