apschedule的定時(shí)任務(wù)實(shí)例(python)
1:方法一:直接代碼配置定時(shí)任務(wù)
使用APScheduler的BackgroundScheduler直接配置多個(gè)定時(shí)任務(wù),通過環(huán)境變量控制執(zhí)行間隔
import os
from apscheduler.schedulers.background import BackgroundScheduler
def init_scheduler():
"""初始化多個(gè)定時(shí)任務(wù)"""
scheduler = BackgroundScheduler(timezone="Asia/Shanghai")
# 定義任務(wù)配置
tasks_config = [
{
'func': sync_analysis_s7_data,
'name': '同步AnalysisS7數(shù)據(jù)',
'interval': int(os.getenv("TASK_INTERVAL_S7", 10)),
'id': 'sync_analysis_s7'
},
{
'func': sync_user_data,
'name': '同步用戶數(shù)據(jù)',
'interval': int(os.getenv("TASK_INTERVAL_USER", 30)),
'id': 'sync_user_data'
},
{
'func': generate_report,
'name': '生成報(bào)表',
'interval': int(os.getenv("TASK_INTERVAL_REPORT", 3600)),
'id': 'generate_report'
}
]
# 動(dòng)態(tài)添加任務(wù)
for task in tasks_config:
scheduler.add_job(
func=task['func'],
trigger="interval",
seconds=task['interval'],
id=task['id'],
name=task['name'],
replace_existing=True
)
print(f"任務(wù)已添加:{task['name']},間隔:{task['interval']}秒")
logger.info(f"任務(wù)已添加:{task['name']},間隔:{task['interval']}秒")
scheduler.start()
print("所有定時(shí)任務(wù)已啟動(dòng)")
logger.info("所有定時(shí)任務(wù)已啟動(dòng)")
return scheduler
2:方法二:YAML配置文件管理
建一個(gè)配置文件 tasks.yaml
通過YAML文件定義任務(wù)配置,支持interval和cron兩種觸發(fā)器類型
tasks:
- name: "同步AnalysisS7數(shù)據(jù)"
function: "sync_analysis_s7_data"
interval_seconds: 10
id: "sync_analysis_s7"
- name: "同步用戶數(shù)據(jù)"
function: "sync_user_data"
interval_seconds: 30
id: "sync_user_data"
- name: "生成報(bào)表"
function: "generate_report"
interval_seconds: 3600
id: "generate_report"
- name: "清理日志"
function: "clean_logs"
cron: "0 2 * * *" # 每天凌晨2點(diǎn)執(zhí)行
id: "clean_logs"
對(duì)應(yīng)的實(shí)現(xiàn)代碼
import yaml
from apscheduler.schedulers.background import BackgroundScheduler
def load_tasks_from_yaml(config_path):
"""從YAML配置文件加載任務(wù)"""
with open(config_path, 'r', encoding='utf-8') as f:
config = yaml.safe_load(f)
return config['tasks']
def get_function_by_name(name):
"""根據(jù)名稱獲取對(duì)應(yīng)的函數(shù)對(duì)象"""
functions = {
'sync_analysis_s7_data': sync_analysis_s7_data,
'sync_user_data': sync_user_data,
'generate_report': generate_report,
'clean_logs': clean_logs
}
return functions.get(name)
def init_scheduler():
"""基于配置文件初始化定時(shí)任務(wù)"""
scheduler = BackgroundScheduler(timezone="Asia/Shanghai")
# 加載任務(wù)配置
tasks = load_tasks_from_yaml('tasks.yaml')
# 添加任務(wù)
for task in tasks:
func = get_function_by_name(task['function'])
if not func:
logger.warning(f"未找到函數(shù): {task['function']}")
continue
# 支持interval和cron兩種觸發(fā)器
if 'interval_seconds' in task:
scheduler.add_job(
func=func,
trigger="interval",
seconds=task['interval_seconds'],
id=task['id'],
name=task['name'],
replace_existing=True
)
print(f"間隔任務(wù)已添加:{task['name']},間隔:{task['interval_seconds']}秒")
elif 'cron' in task:
cron_parts = task['cron'].split()
scheduler.add_job(
func=func,
trigger="cron",
minute=cron_parts[0],
hour=cron_parts[1],
day=cron_parts[2],
month=cron_parts[3],
day_of_week=cron_parts[4],
id=task['id'],
name=task['name'],
replace_existing=True
)
print(f"Cron任務(wù)已添加:{task['name']},調(diào)度:{task['cron']}")
scheduler.start()
print("所有定時(shí)任務(wù)已啟動(dòng)")
return scheduler
3: 裝飾器方式自動(dòng)注冊(cè)任務(wù)
使用裝飾器自動(dòng)收集任務(wù)配置,簡(jiǎn)化任務(wù)注冊(cè)過程
from functools import wraps
from apscheduler.schedulers.background import BackgroundScheduler
# 全局任務(wù)注冊(cè)表
_task_registry = []
def scheduled_task(name, interval_seconds=None, cron=None, task_id=None):
"""裝飾器:注冊(cè)定時(shí)任務(wù)"""
def decorator(func):
_task_registry.append({
'func': func,
'name': name,
'interval_seconds': interval_seconds,
'cron': cron,
'id': task_id or func.__name__
})
return func
return decorator
# 使用裝飾器定義任務(wù)
@scheduled_task(name="同步AnalysisS7數(shù)據(jù)", interval_seconds=10)
def sync_analysis_s7_data():
pass
@scheduled_task(name="同步用戶數(shù)據(jù)", interval_seconds=30)
def sync_user_data():
pass
@scheduled_task(name="每日?qǐng)?bào)告", cron="0 9 * * *") # 每天9點(diǎn)執(zhí)行
def daily_report():
pass
def init_scheduler():
"""初始化所有裝飾器注冊(cè)的任務(wù)"""
scheduler = BackgroundScheduler(timezone="Asia/Shanghai")
for task_info in _task_registry:
kwargs = {
'func': task_info['func'],
'id': task_info['id'],
'name': task_info['name'],
'replace_existing': True
}
# 根據(jù)配置選擇觸發(fā)器類型
if task_info['interval_seconds']:
kwargs.update({
'trigger': "interval",
'seconds': task_info['interval_seconds']
})
elif task_info['cron']:
cron_parts = task_info['cron'].split()
kwargs.update({
'trigger': "cron",
'minute': cron_parts[0],
'hour': cron_parts[1],
'day': cron_parts[2],
'month': cron_parts[3],
'day_of_week': cron_parts[4]
})
scheduler.add_job(**kwargs)
print(f"任務(wù)已添加:{task_info['name']}")
scheduler.start()
print("所有定時(shí)任務(wù)已啟動(dòng)")
return scheduler
4:注意最終記得要關(guān)閉定時(shí)任務(wù)
4-1:方法一
def signal_handler(signum, frame):
"""信號(hào)處理函數(shù)"""
print("接收到關(guān)閉信號(hào),正在停止定時(shí)任務(wù)...")
scheduler.shutdown()
print("定時(shí)任務(wù)已停止")
sys.exit(0)
# 注冊(cè)信號(hào)處理器
signal.signal(signal.SIGINT, signal_handler) # Ctrl+C
signal.signal(signal.SIGTERM, signal_handler) # 終止信號(hào)
4-2:方法二
import atexit
from apscheduler.schedulers.background import BackgroundScheduler
scheduler = BackgroundScheduler(timezone="Asia/Shanghai")
scheduler.add_job(sync_analysis_s7_data, "interval", seconds=10)
scheduler.start()
def cleanup():
"""清理函數(shù)"""
print("正在清理資源...")
scheduler.shutdown()
# 注冊(cè)退出時(shí)的清理函數(shù)
atexit.register(cleanup)
4-3:方法三
只是依賴FastApi框架
@app.on_event("shutdown")
async def shutdown_event():
"""應(yīng)用關(guān)閉時(shí)執(zhí)行"""
# 停止定時(shí)任務(wù)
scheduler.shutdown()
logger.info("===== AnalysisS7數(shù)據(jù)服務(wù)關(guān)閉 =====")
5:總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
struts2實(shí)現(xiàn)多文件上傳的示例代碼
本篇文章主要介紹了struts2實(shí)現(xiàn)多文件上傳的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-03-03
Java中正則表達(dá)式的語法以及matches方法的使用方法
正則表達(dá)式(Regular Expression)是一門簡(jiǎn)單語言的語法規(guī)范,是強(qiáng)大、便捷、高效的文本處理工具,這篇文章主要給大家介紹了關(guān)于Java中正則表達(dá)式的語法以及matches方法的使用方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-05-05
Java項(xiàng)目實(shí)現(xiàn)尋找迷宮出路
這篇文章主要為大家詳細(xì)介紹了Java項(xiàng)目實(shí)現(xiàn)尋找迷宮出路,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05
Java實(shí)現(xiàn)Excel導(dǎo)入導(dǎo)出數(shù)據(jù)庫的方法示例
這篇文章主要介紹了Java實(shí)現(xiàn)Excel導(dǎo)入導(dǎo)出數(shù)據(jù)庫的方法,結(jié)合實(shí)例形式分析了java針對(duì)Excel的讀寫及數(shù)據(jù)庫操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-08-08
Java Annotation(Java 注解)的實(shí)現(xiàn)代碼
本篇文章介紹了,Java Annotation(Java 注解)的實(shí)現(xiàn)代碼。需要的朋友參考下2013-05-05
SpringBoot對(duì)數(shù)據(jù)庫用戶名和密碼進(jìn)行加密的兩種方案
在當(dāng)今互聯(lián)網(wǎng)時(shí)代,?數(shù)據(jù)庫安全的重要性不言而喻,作為Java開發(fā)的主流框架,Spring Boot項(xiàng)目通常需要連接數(shù)據(jù)庫,而數(shù)據(jù)庫的?用戶名和密碼作為最敏感的信息之一,所以本文給大家詳細(xì)介紹兩種主流的數(shù)據(jù)源配置加密方案,需要的朋友可以參考下2025-12-12
Java實(shí)現(xiàn)音頻轉(zhuǎn)文本的示例代碼(語音識(shí)別)
Java中實(shí)現(xiàn)音頻轉(zhuǎn)文本通常涉及使用專門的語音識(shí)別服務(wù),本文主要介紹了Java實(shí)現(xiàn)音頻轉(zhuǎn)文本的示例代碼(語音識(shí)別),具有一定的參考價(jià)值,感興趣的可以了解一下2024-05-05

