Ustawić zaplanowaną pracę?

519

Pracuję nad aplikacją internetową przy użyciu Django i jestem ciekawy, czy istnieje sposób, aby zaplanować okresowe uruchamianie zadania.

Zasadniczo chcę po prostu przeglądać bazę danych i dokonywać automatycznych, regularnych obliczeń / aktualizacji, ale nie mogę znaleźć dokumentacji na ten temat.

Czy ktoś wie, jak to skonfigurować?

Wyjaśnienie: Wiem, że mogę skonfigurować cronzadanie, aby to zrobić, ale jestem ciekawy, czy w Django jest jakaś funkcja zapewniająca tę funkcjonalność. Chciałbym, aby ludzie mogli sami wdrożyć tę aplikację bez konieczności przeprowadzania dużej konfiguracji (najlepiej zero).

Rozważałem uruchomienie tych działań „z mocą wsteczną”, po prostu sprawdzając, czy zadanie powinno zostać uruchomione od czasu ostatniego wysłania żądania do witryny, ale mam nadzieję na coś nieco czystszego.

TM.
źródło
1
Jeśli jesteś witryną o wysokiej wydajności i już korzystasz z RabbitMQ, oto sposób na obejście crona: Korzystanie z AMQP do planowania podobnego do crona
Van Gale
Jeśli dobrze rozumiem, musisz zaplanować niektóre zadania w Django. Najlepszą rzeczą, jaką obecnie znajduję, jest ta: celery.github.com/celery/index.html
Ali Nikneshan
co o tym sądzisz? github.com/reavis/django-cron
Domenico Monaco,
Kleszcz został jednak po to, aby uniknąć całej tej pracy. [Oświadczenie] Buduję tik.
Siscia,
2
github.com/coleifer/huey Huey potrzebuje tutaj wzmianki. Instalacja Django jest niezwykle łatwa.
Brandon Bertelsen,

Odpowiedzi:

363

Jednym z rozwiązań, które zastosowałem, jest:

1) Utwórz niestandardowe polecenie zarządzania , np

python manage.py my_cool_command

2) Użyj cron(w systemie Linux) lub at(w systemie Windows), aby uruchomić polecenie w wymaganych godzinach.

Jest to proste rozwiązanie, które nie wymaga instalowania dużego stosu AMQP. Istnieją jednak zalety korzystania z czegoś takiego jak seler, wspomniane w innych odpowiedziach. W szczególności, dzięki Selerowi fajnie jest nie rozkładać logiki aplikacji na pliki crontab. Jednak rozwiązanie cron działa całkiem nieźle dla małych i średnich aplikacji i tam, gdzie nie potrzebujesz wielu zewnętrznych zależności.

EDYTOWAĆ:

W późniejszej wersji systemu Windows to atpolecenie jest nieaktualne w systemie Windows 8, Server 2012 i nowszych. Możesz użyć schtasks.exedo tego samego zastosowania.

**** UPDATE **** To nowy link do dokumentu django do pisania niestandardowego polecenia zarządzania

Brian Neal
źródło
5
Czy jest to sposób na zrobienie tego bez usług zewnętrznych, ale używając tylko działającego procesu frameworka django?
sergzach
4
Aplikacja @Brian_Neal django_cron.
sergzach,
2
Pomóż mi zrozumieć, w jaki sposób uruchomię polecenie zarządzania w środowisku wirtualnym przy użyciu crona w ostatnim dniu każdego miesiąca.
mmrs151
2
@sergzach Śledziłem ten komentarz i okazało się, że są dwa pakiety o tej nazwie. Django-cron na Google Code i django-cron na Github . Są nieco inne, ale oba są interesujące. Oba pozwalają definiować crony w sposób „djangonowy”. Pierwszy jest nieco starszy i ma na celu pracę bez zewnętrznego zadania (np. Cron). Drugi natomiast wymaga ustawienia crona do uruchomienia, python manage.py runcronsktóry następnie uruchamia wszystkie crony, które zdefiniowałeś i zarejestrowałeś.
driftcatcher
1
@sergzach Zakładam, że masz na myśli pierwszy, „django-cron w Google Code”. Masz rację co do tego. Właśnie dlatego wybrałem drugi, „django-cron na GitHub”, ponieważ dzięki temu masz prostą konfigurację / zarządzanie crontabem - tylko jeden crontab, odnoszący się do polecenia zarządzania - ale ponieważ używasz osobnego proces cron pozwala uniknąć tego problemu synchronizacji (o ile wiem).
driftcatcher
152

Seler jest rozproszoną kolejką zadań, zbudowaną na platformie AMQP (RabbitMQ). Obsługuje również zadania okresowe w sposób podobny do crona (patrz zadania okresowe ). W zależności od aplikacji może to być warte spojrzenia.

Seler jest dość łatwy do skonfigurowania za pomocą django ( docs ), a zadania okresowe faktycznie pomijają pominięte zadania w przypadku przestoju. Seler ma również wbudowane mechanizmy ponownej próby na wypadek niepowodzenia zadania.

dln
źródło
51

Odkryliśmy, że moim zdaniem jest to aplikacja strukturalna. że powyższe rozwiązanie Briana również nawiązuje. Bardzo chcielibyśmy otrzymać wszelkie opinie!

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

Zawiera jedno polecenie zarządzania:

./manage.py runcrons

To działa. Każdy cron jest modelowany jako klasa (więc jest to wszystko OO), a każdy cron działa na innej częstotliwości, a my upewniamy się, że ten sam typ cron nie działa równolegle (w przypadku, gdy sami cron potrzebują więcej czasu niż ich częstotliwość!)

chachra
źródło
5
@chachra Przepraszam, wiem, że to może być głupie pytanie, ale czy to zadziała na Windowsie, atczy było specjalnie zaprojektowane do pracy cron?
Bruno Finger,
38

Jeśli używasz standardowego systemu operacyjnego POSIX, używasz crona .

Jeśli używasz systemu Windows, używasz w .

Napisz polecenie zarządzania Django do

  1. Dowiedz się, na jakiej platformie się znajdują.

  2. Wykonaj odpowiednie polecenie „AT” dla swoich użytkowników lub zaktualizuj plik crontab dla swoich użytkowników.

S.Lott
źródło
10
Jeśli to możliwe, chciałbym, aby został on zwinięty w mojej aplikacji django.
TM.
@TM: Co oznacza „roll-up do mojej aplikacji django”? Proszę wyjaśnić swoje pytanie.
S.Lott
10
Chciałbym, aby ludzie mogli łatwo wdrożyć tę aplikację bez konieczności samodzielnego konfigurowania zadań cron.
TM.
1
Zawsze możesz zawinąć interfejs cron do swojej aplikacji.
monkut
BSD, Mac i dowolny system operacyjny typu Unix mają cron.
DylanYoung
23

Interesująca nowa aplikacja Django z wtyczką: django-chronograph

Musisz tylko dodać jeden wpis crona, który działa jak licznik czasu, i masz bardzo ładny interfejs administratora Django do skryptów do uruchomienia.

Van Gale
źródło
2
django-chronograph jest nieobsługiwany. Widelec ma się znacznie lepiej: github.com/chrisspen/django-chroniker
Menda
16

Spójrz na Django Poor Man's Cron, która jest aplikacją Django, która korzysta ze spambotów, robotów indeksujących wyszukiwarki i podobnych do uruchamiania zaplanowanych zadań w przybliżeniu w regularnych odstępach czasu

Zobacz: http://code.google.com/p/django-poormanscron/

użytkownik41767
źródło
2
Zakłada się również, że twoja aplikacja Django jest dostępna z Internetu, co nie miałoby miejsca w przypadku wdrożeń w sieciach LAN i VPN.
TimH - Codidact
10

Jakiś czas temu miałem dokładnie taki sam wymóg i ostatecznie rozwiązałem go za pomocą APScheduler ( instrukcja obsługi )

To sprawia, że ​​zadania planowania są bardzo proste i zachowują niezależność od wykonywania niektórych kodów na podstawie żądań. Poniżej znajduje się prosty przykład.

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

Mam nadzieję, że to komuś pomoże!

PhoenixDev
źródło
9

Sugestia Briana Neala, aby uruchamiać polecenia zarządzania za pomocą crona, działa dobrze, ale jeśli szukasz czegoś bardziej solidnego (ale nie tak skomplikowanego jak Selery), zajrzałbym do biblioteki takiej jak Kronos :

# app/cron.py

import kronos

@kronos.register('0 * * * *')
def task():
    pass
Johannes Gorset
źródło
9

RabbitMQ i Seler mają więcej funkcji i możliwości obsługi zadań niż Cron. Jeśli niepowodzenie zadania nie stanowi problemu i uważasz, że poradzisz sobie z uszkodzonymi zadaniami w następnym wywołaniu, wtedy Cron jest wystarczający.

Celery i AMQP pozwolą ci poradzić sobie z przerwanym zadaniem i będzie ono wykonywane ponownie przez innego pracownika (pracownicy Selera nasłuchują następnego zadania do pracy), dopóki nie max_retrieszostanie osiągnięty atrybut zadania . Możesz nawet wywoływać zadania w przypadku awarii, takie jak rejestrowanie awarii lub wysyłanie wiadomości e-mail do administratora po max_retriesosiągnięciu.

I możesz dystrybuować serwery Selery i AMQP, gdy potrzebujesz skalować swoją aplikację.

Ravi Kumar
źródło
8

Ja osobiście korzystam z crona, ale planowanie zadań części rozszerzeń django wygląda interesująco.

Van Gale
źródło
Nadal zależy od crona do wyzwalania, po prostu dodaje kolejną warstwę abstrakcji pomiędzy nimi. Nie jestem pewien, czy warto.
Carl Meyer
Zgadzam się i po przemyśleniu nie chcę żądać oprogramowania pośredniego spowalniającego moją witrynę (ala poormanscron powyżej), gdy cron i tak może wykonać to lepiej.
Van Gale
7

Chociaż Airflow nie jest częścią Django, jest nowszym projektem (od 2016 r.), Który jest przydatny do zarządzania zadaniami.

Airflow to system automatyzacji i planowania przepływu pracy, którego można używać do tworzenia i zarządzania potokami danych. Internetowy interfejs użytkownika zapewnia programistom szereg opcji zarządzania i przeglądania tych potoków.

Przepływ powietrza jest napisany w języku Python i zbudowany przy użyciu Flask.

Airflow został stworzony przez Maxime Beauchemin z Airbnb i otwarty na wiosnę 2015 roku. Dołączył do programu inkubacyjnego Apache Software Foundation zimą 2016 roku. Oto strona projektu Git i dodatkowe informacje dodatkowe .

Alexander
źródło
6

Umieść na górze pliku 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
Matt McCormick
źródło
6

Właśnie pomyślałem o tym dość prostym rozwiązaniu:

  1. Zdefiniuj funkcję widoku do_work (req, param), tak jak w przypadku każdego innego widoku, z odwzorowaniem adresu URL, zwróć odpowiedź HttpResponse i tak dalej.
  2. Skonfiguruj zadanie cron z własnymi preferencjami czasowymi (lub używając AT lub Zaplanowanych zadań w systemie Windows), które uruchamiają curl http: // localhost / your / mapped / url? Param = wartość .

Możesz dodać parametry, ale tylko dodać parametry do adresu URL.

Powiedzcie mi co myślicie.

[Aktualizacja] Teraz używam polecenia runjob z rozszerzeń django zamiast curl.

Mój cron wygląda mniej więcej tak:

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

... i tak dalej codziennie, co miesiąc itp. ” Możesz również skonfigurować go do uruchamiania określonego zadania.

Uważam, że jest to łatwiejsze do zarządzania i czystsze. Nie wymaga mapowania adresu URL do widoku. Po prostu określ swoją klasę pracy i tabelę zadań i gotowe.

Michał
źródło
1
Jedynym problemem, który wyczuwam, jest niekoniecznie zwiększanie obciążenia aplikacji i przepustowości, aby uruchomić zadanie w tle, które lepiej byłoby uruchomić „wewnętrznie” i niezależnie od aplikacji obsługującej. Ale poza tym jest to sprytniejszy i bardziej ogólny django-cron, ponieważ może być nawet wywoływany przez agentów spoza serwera aplikacji!
nemesisfixx
Masz rację, dlatego przeniosłem się do korzystania z zadań z rozszerzeń poleceń django. Zobacz moją aktualizację mojej odpowiedzi.
Michael
4

po części kodu mogę pisać wszystko tak jak moje 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)
#######################################

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

Xiaohei
źródło
3

Zdecydowanie powinieneś sprawdzić django-q! Nie wymaga dodatkowej konfiguracji i prawdopodobnie ma wszystko, co potrzebne do obsługi wszelkich problemów produkcyjnych w projektach komercyjnych.

Jest aktywnie rozwijany i bardzo dobrze integruje się z django, django ORM, mongo, redis. Oto moja konfiguracja:

# 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,
},
}
saran3h
źródło
3

Django APScheduler for Scheduler Jobs. Advanced Python Scheduler (APScheduler) to biblioteka języka Python, która pozwala zaplanować wykonanie kodu w języku Python później, tylko raz lub okresowo. Możesz dodawać nowe oferty pracy lub usuwać stare w dowolnym momencie.

Uwaga: Jestem autorem tej biblioteki

Zainstaluj APScheduler

pip install apscheduler

Wyświetl funkcję pliku, aby zadzwonić

nazwa pliku: scheduler_jobs.py

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

Konfigurowanie harmonogramu

stwórz plik execute.py i dodaj poniższe kody

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

Twoje pisemne funkcje Tutaj funkcje harmonogramu są zapisane w harmonogramie_zadania

import scheduler_jobs 

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

Połącz plik do wykonania

Teraz dodaj poniższy wiersz na dole pliku Url

import execute
Chandan Sharma
źródło
2

Miałem dzisiaj coś podobnego z twoim problemem.

Nie chciałem, żeby to obsłużył serwer trhough cron (a większość bibliotek była w końcu tylko pomocnikami crona).

Więc stworzyłem moduł planowania i podłączyłem go do init .

To nie jest najlepsze podejście, ale pomaga mi mieć cały kod w jednym miejscu i jego wykonanie związane z główną aplikacją.

Fabricio Buzeto
źródło
2

Tak, powyższa metoda jest świetna. I próbowałem niektóre z nich. W końcu znalazłem taką metodę:

    from threading import Timer

    def sync():

        do something...

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

Tak jak rekurencyjny .

Ok, mam nadzieję, że ta metoda spełni twoje wymagania. :)

Ni Xiaoni
źródło
1
Zatrzyma się, jeśli twoje „coś” kiedykolwiek zawiedzie, więc upewnij się, że poradzisz sobie ze wszystkimi wyjątkami w tym zakresie. Nawet wtedy serwer internetowy może w pewnym momencie zabić twój wątek, prawda?
Lutz Prechelt
2

Bardziej nowoczesnym rozwiązaniem (w porównaniu do Celery) jest Django Q: https://django-q.readthedocs.io/en/latest/index.html

Ma świetną dokumentację i jest łatwy do odczytania. Brakuje obsługi systemu Windows, ponieważ system Windows nie obsługuje rozwidlania procesów. Ale działa dobrze, jeśli tworzysz środowisko programistyczne za pomocą podsystemu Windows for Linux.

devdrc
źródło
Wygląda na to, że nadal możesz go używać w trybie pojedynczego klastra w systemie Windows
Yushin Washio,
1

Używam selera do tworzenia okresowych zadań. Najpierw musisz zainstalować go w następujący sposób:

pip install django-celery

Nie zapomnij zarejestrować się django-celeryw ustawieniach, a wtedy możesz zrobić coś takiego:

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
David Felipe Camargo Polo
źródło
2
Zauważam, że ta rada jest nieaktualna i możesz bezpośrednio zintegrować seler. Szczegółowe informacje można znaleźć na stronie pypi.python.org/pypi/django-celery .
Peter Brittain,
Dokumenty Selera mówią, że była to zmiana w wersji 3.1. Sam jeszcze tego nie próbowałem.
Peter Brittain,
1

Nie jestem pewien, czy będzie to przydatne dla każdego, ponieważ musiałem zapewnić innym użytkownikom systemu planowanie zadań, nie dając im dostępu do faktycznego harmonogramu zadań serwera (systemu Windows), stworzyłem tę aplikację wielokrotnego użytku.

Uwaga: użytkownicy mają dostęp do jednego folderu współdzielonego na serwerze, na którym mogą utworzyć wymagany plik polecenia / zadania / .bat. To zadanie można następnie zaplanować za pomocą tej aplikacji.

Nazwa aplikacji to Django_Windows_Scheduler

Zrzut ekranu: wprowadź opis zdjęcia tutaj

tylko 10 minut
źródło
0

Jeśli chcesz czegoś bardziej niezawodnego niż seler , wypróbuj TaskHawk, który jest oparty na AWS SQS / SNS .

Patrz: http://taskhawk.readthedocs.io

Sriram
źródło
0

W przypadku prostych projektów zadokowanych nie widziałem żadnej istniejącej odpowiedzi.

Napisałem więc bardzo proste rozwiązanie bez potrzeby korzystania z zewnętrznych bibliotek lub wyzwalaczy, które działają same. Nie wymaga zewnętrznego os-crona, powinien działać w każdym środowisku.

Działa poprzez dodanie oprogramowania pośredniego: 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',
    ...
]
żółty
źródło
0

Prostym sposobem jest napisanie niestandardowego polecenia powłoki, patrz Dokumentacja Django i wykonanie go za pomocą cronjob na Linuksie. Jednak zdecydowanie polecam korzystanie z brokera wiadomości, takiego jak RabbitMQ w połączeniu z selerem. Może możesz rzucić okiem na ten samouczek

Hamfri
źródło