it-swarm.com.de

Django - Ein geplanter Job einrichten?

Ich habe an einer Web-App mit Django gearbeitet und bin neugierig, ob es eine Möglichkeit gibt, einen Job periodisch zu planen. 

Im Grunde möchte ich nur die Datenbank durchgehen und regelmäßig und regelmäßig Berechnungen/Aktualisierungen vornehmen, aber ich kann anscheinend keine Dokumentation dazu finden.

Weiß jemand, wie man das einrichtet?

Zur Klarstellung: Ich weiß, dass ich einen cron-Job einrichten kann, aber ich bin neugierig, ob es in Django eine Funktion gibt, die diese Funktionalität bietet. Ich möchte, dass die Leute diese App selbst bereitstellen können, ohne viele Konfigurationsschritte durchführen zu müssen (vorzugsweise Null).

Ich habe in Erwägung gezogen, diese Aktionen "rückwirkend" auszulösen, indem ich einfach prüfe, ob ein Job ausgeführt werden sollte, seit eine Anfrage zuletzt an die Site gesendet wurde. Ich hoffe jedoch auf etwas saubereres.

450
TM.

Eine Lösung, die ich verwendet habe, ist dies zu tun:

1) Erstellen Sie einen benutzerdefinierten Verwaltungsbefehl , z. 

python manage.py my_cool_command

2) Verwenden Sie cron (unter Linux) oder at (unter Windows), um meinen Befehl zu den erforderlichen Zeiten auszuführen.

Dies ist eine einfache Lösung, für die kein starker AMQP-Stack installiert werden muss. Es gibt jedoch gute Vorteile, wenn man etwas wie Sellerie verwendet, wie in den anderen Antworten erwähnt. Bei Celery ist es besonders schön, dass Sie Ihre Anwendungslogik nicht in Crontab-Dateien verteilen müssen. Die cron-Lösung funktioniert jedoch sehr gut für kleine bis mittelgroße Anwendungen, bei denen Sie keine großen externen Abhängigkeiten wünschen.

BEARBEITEN:

In späteren Versionen von Windows ist der Befehl at für Windows 8, Server 2012 und höher veraltet. Sie können schtasks.exe für dieselbe Verwendung verwenden.

325
Brian Neal

Celery ist eine verteilte Task-Warteschlange, die auf AMQP (RabbitMQ) basiert. Es behandelt auch periodische Aufgaben cronartig (siehe periodische Aufgaben ). Abhängig von Ihrer App ist es vielleicht einen Blick wert.

Sellerie ist mit Django ( docs ) ziemlich einfach einzurichten, und bei periodischen Aufgaben werden übersprungene Aufgaben bei Ausfallzeiten übersprungen. Celery verfügt auch über integrierte Wiederholungsmechanismen für den Fall, dass eine Aufgabe fehlschlägt.

128
dln

Wir haben aus meiner Sicht eine strukturierte App gefunden. dass die Lösung von Brian über alle Anspielungen hinausgeht. Würde mich über Feedback freuen!

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

Es gibt einen Verwaltungsbefehl:

./manage.py runcrons

Das macht den Job. Jeder Cron wird als Klasse modelliert (also alle als OO) und jeder Cron läuft mit einer anderen Frequenz. Wir stellen sicher, dass derselbe Cronentyp nicht parallel läuft (falls Cron selbst länger als ihre Frequenz laufen müssen!)

Vielen Dank!

46
chachra

Wenn Sie ein Standard-POSIX-Betriebssystem verwenden, verwenden Sie cron .

Wenn Sie Windows verwenden, verwenden Sie at .

Schreiben Sie einen Django-Verwaltungsbefehl an 

  1. Finde heraus, auf welcher Plattform sie sich befinden.

  2. Führen Sie entweder den entsprechenden "AT" -Befehl für Ihre Benutzer aus, oder aktualisieren Sie die Crontab für Ihre Benutzer.

35
S.Lott

Interessante neue steckbare Django-App: Django-Chronograph

Sie müssen nur einen cron-Eintrag hinzufügen, der als Timer fungiert, und Sie haben eine sehr schöne Django-Administrationsoberfläche für die Ausführung der Skripts.

23
Van Gale

Schauen Sie sich Django Poor Man's Cron an, eine Django-App, die Spambots, Suchmaschinen-Indizierungsroboter und dergleichen verwendet, um geplante Aufgaben in ungefähr regelmäßigen Abständen auszuführen

Siehe: http://code.google.com/p/Django-poormanscron/

14
user41767

RabbitMQ und Celery bieten mehr Funktionen und Aufgaben als Cron. Wenn das Fehlschlagen von Aufgaben kein Problem ist und Sie der Meinung sind, dass Sie beim nächsten Anruf mit fehlerhaften Aufgaben fertig werden, ist Cron ausreichend.

Mit Sellerie & AMQP können Sie die fehlerhafte Aufgabe erledigen und diese wird erneut von einem anderen Arbeiter ausgeführt (Celery-Mitarbeiter überwachen die nächste Aufgabe), bis das max_retries-Attribut der Aufgabe erreicht ist. Sie können sogar Aufgaben ausführen, wenn ein Fehler auftritt, z. B. das Protokollieren des Fehlers oder das Senden einer E-Mail an den Administrator, sobald der max_retries erreicht wurde.

Sie können Celery- und AMQP-Server verteilen, wenn Sie Ihre Anwendung skalieren müssen.

9
Ravi Kumar

Brian Neals Vorschlag, Verwaltungsbefehle über cron auszuführen, funktioniert gut, aber wenn Sie nach etwas robusterem suchen (aber nicht so kompliziert wie Celery), würde ich mir eine Bibliothek wie Kronos anschauen:

# app/cron.py

import kronos

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

Ich persönlich benutze cron, aber die Jobs Scheduling Teile von Django-Erweiterungen sehen interessant aus.

8
Van Gale

Fügen Sie Folgendes in Ihre Datei cron.py ein:

#!/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
Matt McCormick

Ich hatte vor einer Weile genau die gleiche Anforderung und endete letztendlich mit APScheduler ( User Guide ).

Es macht das Planen von Jobs extrem einfach und macht es unabhängig von der anforderungsbasierten Ausführung von Code. Das folgende ist ein einfaches Beispiel, das ich in meinem Code verwendet habe.

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

Hoffe das hilft jemandem!

6
PhoenixDev

Ich habe gerade über diese ziemlich einfache Lösung nachgedacht:

  1. Definieren Sie eine View-Funktion do_work (req, param) wie bei jeder anderen Ansicht mit URL-Zuordnung, geben Sie eine HttpResponse usw. zurück.
  2. Richten Sie einen Cron-Job mit Ihren Timing-Einstellungen ein (oder verwenden Sie AT oder Scheduled Tasks in Windows), um curl http: // localhost/your/mapped/url? Param = value auszuführen.

Sie können Parameter hinzufügen, aber nur Parameter zur URL hinzufügen.

Sag mir, was ihr denkt.

[Update] Ich benutze jetzt den runjob-Befehl von Django-extensions anstelle von curl.

Mein Cron sieht ungefähr so ​​aus:

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

... und so weiter für täglich, monatlich usw. '. Sie können es auch so einrichten, dass ein bestimmter Job ausgeführt wird.

Ich finde es überschaubarer und sauberer. Erfordert keine Zuordnung einer URL zu einer Ansicht. Definieren Sie einfach Ihre Jobklasse und Crontab und Sie sind fertig.

6
Michael

Obwohl es kein Teil von Django ist, ist Airflow ein jüngeres Projekt (Stand 2016), das für die Aufgabenverwaltung nützlich ist.

Airflow ist ein Workflow-Automatisierungs- und Zeitplanungssystem, mit dem Daten-Pipelines erstellt und verwaltet werden können. Eine webbasierte Benutzeroberfläche bietet dem Entwickler eine Reihe von Optionen zum Verwalten und Anzeigen dieser Pipelines.

Airflow ist in Python geschrieben und wird mit Flask erstellt.

Airflow wurde von Maxime Beauchemin bei Airbnb entwickelt und im Frühjahr 2015 als Open-Source-Produkt angeboten. Im Winter 2016 trat er dem Inkubationsprogramm der Apache Software Foundation bei. Hier ist die Git-Projektseite und einige Zusatzinformationen Hintergrundinformationen .

6
Alexander

nach dem Teil des Codes kann ich alles wie meine Ansichten schreiben.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/

4
xiaohei

Sie sollten sich unbedingt Django-q! .__ ansehen. Es erfordert keine zusätzliche Konfiguration und hat möglicherweise alles, um Produktionsprobleme bei kommerziellen Projekten zu lösen.

Es ist aktiv entwickelt und integriert sich sehr gut mit Django, Django ORM, Mongo, Redis. Hier ist meine Konfiguration:

# 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,
},
}
2
saran3h

Ich hatte heute etwas Ähnliches mit Ihrem Problem.

Ich wollte nicht, dass es vom Server durch cron (und die meisten libs waren am Ende nur cron-Helfer) gehandhabt wurden.

Also habe ich ein Scheduling-Modul erstellt und an das init angehängt.

Dies ist nicht der beste Ansatz, aber es hilft mir, den gesamten Code an einem einzigen Ort zu haben und dessen Ausführung mit der Haupt-App in Verbindung zu stehen.

2
Fabricio Buzeto

Ja, die obige Methode ist so toll. Und ich habe einige von ihnen ausprobiert. Endlich fand ich eine Methode wie diese:

    from threading import Timer

    def sync():

        do something...

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

Genau wie rekursiv .

Ok, ich hoffe, diese Methode kann Ihre Anforderungen erfüllen. :)

2
Ni Xiaoni

Ich verwende Sellerie, um meine periodischen Aufgaben zu erstellen. Zuerst müssen Sie es wie folgt installieren:

pip install Django-celery

Vergessen Sie nicht, Django-celery in Ihren Einstellungen zu registrieren und dann könnten Sie so etwas tun:

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

Ich bin mir nicht sicher, ob dies für alle nützlich sein wird, da ich andere Benutzer des Systems zur Planung der Jobs bereitstellen musste, ohne ihnen Zugriff auf den eigentlichen Taskplaner des Servers (Windows) zu geben.

Beachten Sie, dass Benutzer Zugriff auf einen freigegebenen Ordner auf dem Server haben, in dem sie die erforderliche Befehls-/Task-/BAT-Datei erstellen können. Diese Aufgabe kann dann mit dieser App geplant werden.

App-Name ist Django_Windows_Scheduler

Bildschirmfoto:  enter image description here

1
just10minutes

Eine modernere Lösung (im Vergleich zu Sellerie) ist Django Q: https://Django-q.readthedocs.io/de/latest/index.html

Es hat eine großartige Dokumentation und ist leicht zu grokieren. Die Windows-Unterstützung fehlt, da Windows Prozess-Forking nicht unterstützt. Es funktioniert jedoch gut, wenn Sie Ihre Entwicklungsumgebung mit dem Windows für Linux-Subsystem erstellen. 

1
devdrc

Wenn Sie etwas zuverlässiger als Sellerie möchten, versuchen Sie TaskHawk, das auf AWS SQS/SNS basiert.

Siehe: http://taskhawk.readthedocs.io

0
Sriram

Eine einfache Möglichkeit ist, einen benutzerdefinierten Shell-Befehl zu schreiben, siehe Django Documentation und ihn mit einem Cronjob unter Linux auszuführen. Ich würde jedoch empfehlen, einen Nachrichtenbroker wie RabbitMQ und Sellerie zu verwenden. Vielleicht können Sie Dieses Tutorial anschauen.

0
Hamfri

Bei einfachen angedockten Projekten konnte ich keine passende Antwort finden.

Also habe ich eine Barebones-Lösung geschrieben, ohne dass externe Bibliotheken oder Trigger erforderlich sind, die von alleine laufen. Kein externer OS-Cron erforderlich, sollte in jeder Umgebung funktionieren.

Es funktioniert, indem Sie eine Middleware hinzufügen: 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
y-spreen