479 Stimmen

Wie bekomme ich einen Cron-ähnlichen Scheduler in Python?

Ich bin auf der Suche nach einer Bibliothek in Python, die Folgendes bietet at y cron wie Funktionalität.

Ich hätte gerne eine reine Python-Lösung, anstatt mich auf Tools zu verlassen, die auf der Box installiert sind; auf diese Weise kann ich auf Maschinen ohne Cron laufen.

Für diejenigen, die nicht vertraut sind mit cron : Sie können Aufgaben auf der Grundlage eines Ausdrucks wie:

 0 2 * * 7 /usr/bin/run-backup # run the backups at 0200 on Every Sunday
 0 9-17/2 * * 1-5 /usr/bin/purge-temps # run the purge temps command, every 2 hours between 9am and 5pm on Mondays to Fridays.

Die Syntax des Cron-Zeitausdrucks ist weniger wichtig, aber ich würde gerne etwas mit dieser Art von Flexibilität haben.

Wenn es nicht etwas gibt, das dies für mich sofort erledigt, wären wir für jeden Vorschlag für die Bausteine dankbar, um so etwas zu erstellen.

bearbeiten Ich bin nicht daran interessiert, Prozesse zu starten, sondern nur "Jobs", die ebenfalls in Python geschrieben sind - Python-Funktionen. Ich denke, dass dies notwendigerweise ein anderer Thread, aber nicht in einem anderen Prozess sein würde.

Zu diesem Zweck bin ich auf der Suche nach der Ausdruckskraft des Cron-Zeit-Ausdrucks, aber in Python.

Cron a gibt es schon seit Jahren, aber ich versuche, so mobil wie möglich zu sein. Ich kann mich nicht auf seine Anwesenheit verlassen.

11voto

Damia Fuentes Punkte 4870

Ich weiß, es gibt viele Antworten, aber eine andere Lösung könnte sein, mit Dekorateure . Dies ist ein Beispiel für die tägliche Wiederholung einer Funktion zu einer bestimmten Zeit. Das Tolle an dieser Methode ist, dass Sie nur die Syntaktischer Zucker zu der Funktion, die Sie planen möchten:

@repeatEveryDay(hour=6, minutes=30)
def sayHello(name):
    print(f"Hello {name}")

sayHello("Bob") # Now this function will be invoked every day at 6.30 a.m

Und der Dekorateur wird wie folgt aussehen:

def repeatEveryDay(hour, minutes=0, seconds=0):
    """
    Decorator that will run the decorated function everyday at that hour, minutes and seconds.
    :param hour: 0-24
    :param minutes: 0-60 (Optional)
    :param seconds: 0-60 (Optional)
    """
    def decoratorRepeat(func):

        @functools.wraps(func)
        def wrapperRepeat(*args, **kwargs):

            def getLocalTime():
                return datetime.datetime.fromtimestamp(time.mktime(time.localtime()))

            # Get the datetime of the first function call
            td = datetime.timedelta(seconds=15)
            if wrapperRepeat.nextSent == None:
                now = getLocalTime()
                wrapperRepeat.nextSent = datetime.datetime(now.year, now.month, now.day, hour, minutes, seconds)
                if wrapperRepeat.nextSent < now:
                    wrapperRepeat.nextSent += td

            # Waiting till next day
            while getLocalTime() < wrapperRepeat.nextSent:
                time.sleep(1)

            # Call the function
            func(*args, **kwargs)

            # Get the datetime of the next function call
            wrapperRepeat.nextSent += td
            wrapperRepeat(*args, **kwargs)

        wrapperRepeat.nextSent = None
        return wrapperRepeat

    return decoratorRepeat

7voto

Nick Punkte 20114

Es gibt keinen "reinen Python"-Weg, dies zu tun, da ein anderer Prozess Python starten müsste, um Ihre Lösung auszuführen. Jede Plattform hat eine oder zwanzig verschiedene Möglichkeiten, Prozesse zu starten und ihren Fortschritt zu überwachen. Auf Unix-Plattformen ist cron der alte Standard. Unter Mac OS X gibt es auch launchd, das das cron-ähnliche Starten mit einer Watchdog-Funktionalität kombiniert, die Ihren Prozess am Leben erhalten kann, wenn Sie das wollen. Sobald Python läuft, können Sie die Funktion Terminmodul um Aufgaben zu planen.

2voto

fdb Punkte 1968

Eine andere triviale Lösung wäre:

from aqcron import At
from time import sleep
from datetime import datetime

# Event scheduling
event_1 = At( second=5 )
event_2 = At( second=[0,20,40] )

while True:
    now = datetime.now()

    # Event check
    if now in event_1: print "event_1"
    if now in event_2: print "event_2"

    sleep(1)

Und die Klasse aqcron.At ist:

# aqcron.py

class At(object):
    def __init__(self, year=None,    month=None,
                 day=None,     weekday=None,
                 hour=None,    minute=None,
                 second=None):
        loc = locals()
        loc.pop("self")
        self.at = dict((k, v) for k, v in loc.iteritems() if v != None)

    def __contains__(self, now):
        for k in self.at.keys():
            try:
                if not getattr(now, k) in self.at[k]: return False
            except TypeError:
                if self.at[k] != getattr(now, k): return False
        return True

1voto

Davide Punkte 16204

Ich weiß nicht, ob es so etwas schon gibt. Es wäre einfach, etwas Eigenes mit Zeit-, Datetime- und/oder Kalendermodulen zu schreiben, siehe http://docs.python.org/library/time.html

Das einzige Problem bei einer Python-Lösung ist, dass Ihr Job immer laufen muss und möglicherweise nach einem Neustart automatisch "wiederbelebt" werden muss, wofür Sie faire sich auf systemabhängige Lösungen verlassen müssen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X