Demasiado práctico: módulo de programación, artefacto de tarea periódica de Python

Si desea ejecutar un determinado script de Python periódicamente en un servidor Linux, la opción más conocida sería un script Crontab, pero Crontab tiene las siguientes desventajas:

1.不方便执行秒级的任务 

2.当需要执行的定时任务有上百个的时候,Crontab的管理就会特别不方便 

Otra opción es Celery, pero la configuración de Celery es más problemática.Si solo necesita una herramienta de programación liviana, Celery no será una buena opción.

Cuando desee utilizar una herramienta de programación de tareas liviana y desee que sea lo más simple posible, fácil de usar, sin dependencias externas y, preferiblemente, capaz de acomodar todas las funciones básicas de Crontab, entonces el módulo Programar es su mejor opción.

Usarlo para programar tareas puede requerir solo unas pocas líneas de código, hágalo:

# Python 实用宝典
import schedule
import time

def job():
    print("I'm working...")

schedule.every(10).minutes.do(job)

while True:
    schedule.run_pending()
    time.sleep(1)

El código anterior indica que la función de trabajo se ejecuta cada 10 minutos, lo cual es muy simple y conveniente. Solo necesita importar el módulo de programación llamando a la  tarea del ciclo de liberación. scedule.every(时间数).时间类型.do(job) 

Las tareas periódicas posteriores al lanzamiento requieren una función para detectar si se ejecutan, por lo que se requiere un ciclo para sondear continuamente esta función. run_pending  While 

La siguiente es una introducción detallada a la instalación y el uso principal y avanzado del módulo Horario.

1. Prepárate

Elija uno de los siguientes métodos para ingresar el comando para instalar dependencias :

1. Abra Cmd en el entorno de Windows (Inicio-Ejecutar-CMD).
2. Abra la Terminal en el entorno MacOS (comando+espacio para ingresar a la Terminal).
3. Si está utilizando el editor VSCode o Pycharm, puede usar directamente la Terminal en la parte inferior de la interfaz.

pip install schedule

2. Uso básico

El uso más básico se ha mencionado al principio del artículo. Aquí hay más ejemplos de tareas de programación:

# Python 实用宝典
import schedule
import time

def job():
    print("I'm working...")

# 每十分钟执行任务
schedule.every(10).minutes.do(job)
# 每个小时执行任务
schedule.every().hour.do(job)
# 每天的10:30执行任务
schedule.every().day.at("10:30").do(job)
# 每个月执行任务
schedule.every().monday.do(job)
# 每个星期三的13:15分执行任务
schedule.every().wednesday.at("13:15").do(job)
# 每分钟的第17秒执行任务
schedule.every().minute.at(":17").do(job)

while True:
    schedule.run_pending()
    time.sleep(1)

Como puede ver, la configuración de mes a segundo está cubierta por el ejemplo anterior. Pero si desea ejecutar la tarea solo una vez, puede configurarla así:

# Python 实用宝典
import schedule
import time

def job_that_executes_once():
    # 此处编写的任务只会执行一次...
    return schedule.CancelJob

schedule.every().day.at('22:30').do(job_that_executes_once)

while True:
    schedule.run_pending()
    time.sleep(1)

Paso de parámetros

Si tiene parámetros para pasar al trabajo a ejecutar, solo necesita hacer esto:

# Python 实用宝典
import schedule

def greet(name):
    print('Hello', name)

# do() 将额外的参数传递给job函数
schedule.every(2).seconds.do(greet, name='Alice')
schedule.every(4).seconds.do(greet, name='Bob')

Obtener todos los trabajos actuales

Si desea obtener todos los trabajos actuales:

# Python 实用宝典
import schedule

def hello():
    print('Hello world')

schedule.every().second.do(hello)

all_jobs = schedule.get_jobs()

Cancelar todos los trabajos

Si se activa algún mecanismo, debe borrar inmediatamente todos los trabajos para el programa actual:

# Python 实用宝典
import schedule

def greet(name):
    print('Hello {}'.format(name))

schedule.every().second.do(greet)

schedule.clear()

Función de etiqueta

Al configurar una asignación, puede agregar una etiqueta a la asignación para la conveniencia de la administración de asignaciones posteriores, de modo que pueda obtener o cancelar asignaciones a través del filtrado de etiquetas.

# Python 实用宝典
import schedule

def greet(name):
    print('Hello {}'.format(name))

# .tag 打标签
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')

# get_jobs(标签):可以获取所有该标签的任务
friends = schedule.get_jobs('friend')

# 取消所有 daily-tasks 标签的任务
schedule.clear('daily-tasks')


Establecer plazos de asignación

Si necesita hacer una tarea que vence en un tiempo determinado, puede usar este método:

# Python 实用宝典
import schedule
from datetime import datetime, timedelta, time

def job():
    print('Boo')

# 每个小时运行作业,18:30后停止
schedule.every(1).hours.until("18:30").do(job)

# 每个小时运行作业,2030-01-01 18:33 today
schedule.every(1).hours.until("2030-01-01 18:33").do(job)

# 每个小时运行作业,8个小时后停止
schedule.every(1).hours.until(timedelta(hours=8)).do(job)

# 每个小时运行作业,11:32:42后停止
schedule.every(1).hours.until(time(11, 33, 42)).do(job)

# 每个小时运行作业,2020-5-17 11:36:20后停止
schedule.every(1).hours.until(datetime(2020, 5, 17, 11, 36, 20)).do(job)

Después de la fecha de vencimiento, el trabajo no podrá ejecutarse.

Ejecute todos los trabajos de inmediato, independientemente de su programación

Si se activa un mecanismo y necesita ejecutar todos los trabajos de inmediato, puede llamar a : schedule.run_all() 

# Python 实用宝典
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()

# 立即运行所有作业,每次作业间隔10秒
schedule.run_all(delay_seconds=10)

3. Uso avanzado

El decorador programa el trabajo.

También puede usar el patrón de decorador si encuentra esta forma de establecer una tarea demasiado detallada:

# Python 实用宝典
from schedule import every, repeat, run_pending
import time

# 此装饰器效果等同于 schedule.every(10).minutes.do(job)
@repeat(every(10).minutes)
def job():
    print("I am a scheduled job")

while True:
    run_pending()
    time.sleep(1)

ejecución paralela

De forma predeterminada, Schedule ejecuta todos los trabajos secuencialmente. La razón detrás de esto es que es difícil encontrar un modelo de ejecución paralela que haga felices a todos.

Sin embargo, puede evitar esta limitación ejecutando cada trabajo en varios subprocesos:

# Python 实用宝典
import threading
import time
import schedule

def job1():
    print("I'm running on thread %s" % threading.current_thread())
def job2():
    print("I'm running on thread %s" % threading.current_thread())
def job3():
    print("I'm running on thread %s" % threading.current_thread())

def run_threaded(job_func):
    job_thread = threading.Thread(target=job_func)
    job_thread.start()

schedule.every(10).seconds.do(run_threaded, job1)
schedule.every(10).seconds.do(run_threaded, job2)
schedule.every(10).seconds.do(run_threaded, job3)

while True:
    schedule.run_pending()
    time.sleep(1)

Inicio sesión

El módulo Schedule también admite el registro de registros, así que use:

# Python 实用宝典
import schedule
import logging

logging.basicConfig()
schedule_logger = logging.getLogger('schedule')
# 日志级别为DEBUG
schedule_logger.setLevel(level=logging.DEBUG)

def job():
    print("Hello, Logs")

schedule.every().second.do(job)

schedule.run_all()

schedule.clear()

El efecto es el siguiente:

DEBUG:schedule:Running *all* 1 jobs with 0s delay in between
DEBUG:schedule:Running job Job(interval=1, unit=seconds, do=job, args=(), kwargs={})
Hello, Logs
DEBUG:schedule:Deleting *all* jobs

manejo de excepciones

El programa no detecta automáticamente las excepciones, las arrojará directamente, lo que causará un problema grave: todos los trabajos posteriores se interrumpirán , por lo que debemos detectar estas excepciones.

Puede capturar manualmente, pero algunas situaciones inesperadas requieren que el programa capture automáticamente, agregar un decorador puede hacerlo:

# Python 实用宝典
import functools

def catch_exceptions(cancel_on_failure=False):
    def catch_exceptions_decorator(job_func):
        @functools.wraps(job_func)
        def wrapper(*args, **kwargs):
            try:
                return job_func(*args, **kwargs)
            except:
                import traceback
                print(traceback.format_exc())
                if cancel_on_failure:
                    return schedule.CancelJob
        return wrapper
    return catch_exceptions_decorator

@catch_exceptions(cancel_on_failure=True)
def bad_task():
    return 1 / 0

schedule.every(5).minutes.do(bad_task)

De esta forma, bad_task se detectarán los errores que se produzcan durante la ejecución , algo muy crítico a la hora de garantizar el normal funcionamiento de las tareas de programación. catch_exceptions  

[aprendizaje de Python]
Socios de aprendizaje de Python, bienvenidos a unirse al nuevo intercambio [Jun Yang]: 1020465983
para discutir el conocimiento de programación juntos, convertirse en un gran dios, hay paquetes de instalación de software, casos prácticos, materiales de aprendizaje en el grupo

Guess you like

Origin blog.csdn.net/weixin_56659172/article/details/124341928