Schedule¶
Planificació de tasques Python per a humans. Executa funcions Python (o qualsevol altre callable) periòdicament utilitzant una sintaxi descriptiva.
Una API fàcil d'usar per programar tasques, feta per a humans. Planificador en procés per a tasques periòdiques. No calen processos addicionals! Molt lleuger i sense dependències externes. Excel·lent cobertura de proves. Provat a Python 3.7, 3.8, 3.9, 3.10 i 3.11
Exemples¶
Exemple bàsic¶
$ pip install schedule
import schedule
import time
def job():
print("I'm working...")
schedule.every(10).minutes.do(job)
schedule.every().hour.do(job)
schedule.every().day.at("10:30").do(job)
schedule.every().monday.do(job)
schedule.every().wednesday.at("13:15").do(job)
schedule.every().day.at("12:42", "Europe/Amsterdam").do(job)
schedule.every().minute.at(":17").do(job)
while True:
schedule.run_pending()
time.sleep(1)
Executar una tasca cada x minuts¶
import schedule
import time
def job():
print("I'm working...")
# Executa la tasca cada 3 segons/minuts/hores/dies/setmanes,
# Començant 3 segons/minuts/hores/dies/setmanes a partir d'ara
schedule.every(3).seconds.do(job)
schedule.every(3).minutes.do(job)
schedule.every(3).hours.do(job)
schedule.every(3).days.do(job)
schedule.every(3).weeks.do(job)
# Executa la tasca cada minut al segon 23
schedule.every().minute.at(":23").do(job)
# Executa la tasca cada hora al minut 42
schedule.every().hour.at(":42").do(job)
# Executa les tasques cada 5 hores, 20 minuts i 30 segons.
# Si l'hora actual és 02:00, la primera execució és a les 06:20:30
schedule.every(5).hours.at("20:30").do(job)
# Executa la tasca cada dia a una HH:MM específica i a la HH:MM:SS següent
schedule.every().day.at("10:30").do(job)
schedule.every().day.at("10:30:42").do(job)
schedule.every().day.at("12:42", "Europe/Amsterdam").do(job)
# Executa la tasca un dia específic de la setmana
schedule.every().monday.do(job)
schedule.every().wednesday.at("13:15").do(job)
schedule.every().minute.at(":17").do(job)
while True:
schedule.run_pending()
time.sleep(1)
Usar un decorador per programar una tasca¶
Fes servir @repeat per programar una funció. Passa-li un interval usant la mateixa sintaxi que l'anterior mentre omets el .do().
from schedule import every, repeat, run_pending
import time
@repeat(every(10).minutes)
def job():
print("I am a scheduled job")
while True:
run_pending()
time.sleep(1)
El decorador @repeat no funciona en mètodes de classe no estàtics.
Passar arguments a una tasca¶
do() passa arguments addicionals a la funció de tasca.
import schedule
def greet(name):
print('Hello', name)
schedule.every(2).seconds.do(greet, name='Alice')
schedule.every(4).seconds.do(greet, name='Bob')
from schedule import every, repeat
@repeat(every().second, "World")
@repeat(every().day, "Mars")
def hello(planet):
print("Hello", planet)
Cancel·lar una tasca¶
Per treure una tasca del planificador, fes servir el mètode schedule.cancel_job(job).
import schedule
def some_task():
print('Hello world')
job = schedule.every().day.at('22:30').do(some_task)
schedule.cancel_job(job)
Executar una tasca una sola vegada¶
Retorna schedule.CancelJob des d'una tasca per treure-la del planificador.
import schedule
import time
def job_that_executes_once():
# Fes alguna feina que només cal fer una vegada...
return schedule.CancelJob
schedule.every().day.at('22:30').do(job_that_executes_once)
while True:
schedule.run_pending()
time.sleep(1)
Obtenir totes les tasques¶
Per recuperar totes les tasques del planificador, fes servir schedule.get_jobs().
import schedule
def hello():
print('Hello world')
schedule.every().second.do(hello)
all_jobs = schedule.get_jobs()
Cancel·lar totes les tasques¶
Per treure totes les tasques del planificador, fes servir schedule.clear().
import schedule
def greet(name):
print('Hello {}'.format(name))
schedule.every().second.do(greet)
schedule.clear()
Obtenir diverses tasques filtrades per etiquetes¶
Pots recuperar un grup de tasques del planificador seleccionant-les mitjançant un identificador únic.
import schedule
def greet(name):
print('Hello {}'.format(name))
schedule.every().day.do(greet, 'Andrea').tag('daily-tasks', 'friend')
schedule.every().hour.do(greet, 'John').tag('hourly-tasks', 'friend')
schedule.every().hour.do(greet, 'Monica').tag('hourly-tasks', 'customer')
schedule.every().day.do(greet, 'Derek').tag('daily-tasks', 'guest')
friends = schedule.get_jobs('friend')
Retornarà una llista de totes les tasques etiquetades com a friend.
Cancel·lar diverses tasques filtrades per etiquetes¶
Pots cancel·lar la programació d'un grup de tasques seleccionant-les mitjançant un identificador únic.
import schedule
def greet(name):
print('Hello {}'.format(name))
schedule.every().day.do(greet, 'Andrea').tag('daily-tasks', 'friend')
schedule.every().hour.do(greet, 'John').tag('hourly-tasks', 'friend')
schedule.every().hour.do(greet, 'Monica').tag('hourly-tasks', 'customer')
schedule.every().day.do(greet, 'Derek').tag('daily-tasks', 'guest')
schedule.clear('daily-tasks')
Evitarà que totes les tasques etiquetades com a daily-tasks es tornin a executar.
Executar una tasca a intervals aleatoris¶
def my_job():
print('Foo')
# Executa cada 5 a 10 segons.
schedule.every(5).to(10).seconds.do(my_job)
every(A).to(B).seconds executa la funció de tasca cada N segons de tal manera que A <= N <= B.
Executar una tasca fins a un moment determinat¶
import schedule
from datetime import datetime, timedelta, time
def job():
print('Boo')
# executa la tasca fins a les 18:30 d'avui
schedule.every(1).hours.until("18:30").do(job)
# executa la tasca fins al 2030-01-01 18:33
schedule.every(1).hours.until("2030-01-01 18:33").do(job)
# Programa una tasca per executar-se durant les properes 8 hores
schedule.every(1).hours.until(timedelta(hours=8)).do(job)
# Executa my_job fins avui a les 11:33:42
schedule.every(1).hours.until(time(11, 33, 42)).do(job)
# executa la tasca fins a un datetime específic
schedule.every(1).hours.until(datetime(2020, 5, 17, 11, 36, 20)).do(job)
El mètode until estableix la data límit de les tasques. La tasca no s'executarà després de la data límit.
Temps fins a la propera execució¶
schedule.idle_seconds() s'usa per obtenir el nombre de segons fins que s'executi la propera tasca programada. El valor retornat és negatiu si les properes tasques programades estaven previstes per executar-se en el passat. Retorna None si no hi ha tasques programades.
import schedule
import time
def job():
print('Hello')
schedule.every(5).seconds.do(job)
while 1:
n = schedule.idle_seconds()
if n is None:
# no hi ha més tasques
break
elif n > 0:
# dorm exactament el temps necessari
time.sleep(n)
schedule.run_pending()
Executar totes les tasques ara, independentment de la seva programació¶
Per executar totes les tasques, independentment de si estan programades per executar-se o no, fes servir schedule.run_all(). Les tasques es reprogramen després de finalitzar, tal com ho farien si s'executessin amb run_pending().
import schedule
def job_1():
print('Foo')
def job_2():
print('Bar')
schedule.every().monday.at("12:40").do(job_1)
schedule.every().tuesday.at("16:40").do(job_2)
schedule.run_all()
# Afegeix l'argument delay_seconds per executar les tasques amb un nombre
# de segons de retard entre elles.
schedule.run_all(delay_seconds=10)
Quan no usar Schedule¶
Siguem honestos, Schedule no és una biblioteca de planificació de "talla única". Aquesta biblioteca està dissenyada per ser una solució senzilla per a problemes de planificació senzills. Probablement hauries de buscar en un altre lloc si necessites:
- Persistència de tasques (recordar el calendari entre reinicis)
- Temporització exacta (execució de precisió inferior a un segon)
- Execució simultània (diversos subprocessos)
- Localització (dies laborables o festius)
Schedule no té en compte el temps que tarda la funció de tasca en executar-se. Per garantir una planificació d'execució estable, has de moure les tasques de llarga durada fora del subprocés principal (on s'executa el planificador). Consulta l'execució paral·lela per obtenir una implementació d'exemple.