本文目录导读:

我来介绍几种Python记录定时任务日志的方法:
使用标准logging模块
import logging
import time
from datetime import datetime
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('scheduler.log', encoding='utf-8'),
logging.StreamHandler() # 同时输出到控制台
]
)
logger = logging.getLogger(__name__)
def scheduled_task():
"""定时任务函数"""
try:
logger.info(f"定时任务开始执行 - {datetime.now()}")
# 你的任务逻辑
time.sleep(2)
logger.info("定时任务执行完成")
except Exception as e:
logger.error(f"定时任务执行失败: {str(e)}")
# 测试
if __name__ == "__main__":
scheduled_task()
基于APScheduler的日志记录
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.events import EVENT_JOB_EXECUTED, EVENT_JOB_ERROR
import logging
from datetime import datetime
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
filename='apscheduler.log'
)
class TaskLogger:
"""任务日志记录类"""
def __init__(self):
self.logger = logging.getLogger('scheduler')
def job_listener(self, event):
"""监听任务事件"""
if event.exception:
self.logger.error(f'任务 {event.job_id} 执行失败: {event.exception}')
else:
self.logger.info(f'任务 {event.job_id} 执行成功,返回值: {event.retval}')
def my_task():
"""示例任务"""
try:
# 记录任务开始
print(f"任务开始执行: {datetime.now()}")
# 任务逻辑
result = "任务执行成功"
# 记录任务结束
print(f"任务完成: {datetime.now()}")
return result
except Exception as e:
print(f"任务失败: {e}")
raise
# 调度器配置
scheduler = BlockingScheduler()
task_logger = TaskLogger()
# 添加任务监听
scheduler.add_listener(task_logger.job_listener, EVENT_JOB_EXECUTED | EVENT_JOB_ERROR)
# 添加定时任务
scheduler.add_job(
my_task,
'interval',
seconds=30,
id='my_task',
name='定时任务示例'
)
try:
scheduler.start()
except KeyboardInterrupt:
scheduler.shutdown()
带日志轮转的高级日志系统
import logging
import logging.handlers
import json
from datetime import datetime
import os
class AdvancedTaskLogger:
"""高级任务日志系统"""
def __init__(self, log_dir='logs'):
self.log_dir = log_dir
if not os.path.exists(log_dir):
os.makedirs(log_dir)
self.setup_loggers()
def setup_loggers(self):
"""配置多个日志处理器"""
# 1. 常规日志(带轮转)
regular_handler = logging.handlers.RotatingFileHandler(
filename=f'{self.log_dir}/task_scheduler.log',
maxBytes=10*1024*1024, # 10MB
backupCount=5,
encoding='utf-8'
)
regular_handler.setLevel(logging.INFO)
# 2. 错误日志
error_handler = logging.handlers.RotatingFileHandler(
filename=f'{self.log_dir}/error.log',
maxBytes=10*1024*1024,
backupCount=3,
encoding='utf-8'
)
error_handler.setLevel(logging.ERROR)
# 3. 性能日志
performance_handler = logging.handlers.RotatingFileHandler(
filename=f'{self.log_dir}/performance.log',
maxBytes=5*1024*1024,
backupCount=2,
encoding='utf-8'
)
performance_handler.setLevel(logging.INFO)
# 格式化器
regular_format = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
performance_format = logging.Formatter(
'%(asctime)s|%(task_name)s|%(duration)s|%(status)s'
)
regular_handler.setFormatter(regular_format)
error_handler.setFormatter(regular_format)
performance_handler.setFormatter(performance_format)
# 常规日志器
self.regular_logger = logging.getLogger('scheduler')
self.regular_logger.addHandler(regular_handler)
self.regular_logger.addHandler(error_handler)
# 性能日志器
self.performance_logger = logging.getLogger('performance')
self.performance_logger.addHandler(performance_handler)
def log_task_execution(self, task_name, duration, status, extra_info=None):
"""记录任务执行日志"""
# 记录常规日志
if status == 'success':
self.regular_logger.info(f"任务 {task_name} 执行成功,耗时: {duration:.2f}秒")
else:
self.regular_logger.error(f"任务 {task_name} 执行失败,耗时: {duration:.2f}秒")
# 记录性能日志
extra_data = {
'task_name': task_name,
'duration': f"{duration:.2f}",
'status': status,
'timestamp': datetime.now().isoformat()
}
if extra_info:
extra_data.update(extra_info)
self.performance_logger.info(json.dumps(extra_data))
# 使用示例
task_logger = AdvancedTaskLogger()
# 模拟任务执行
import time
def run_task():
start_time = time.time()
task_name = "数据备份"
try:
# 执行任务...
time.sleep(2)
duration = time.time() - start_time
task_logger.log_task_execution(
task_name=task_name,
duration=duration,
status='success',
extra_info={'records_processed': 1000}
)
except Exception as e:
duration = time.time() - start_time
task_logger.log_task_execution(
task_name=task_name,
duration=duration,
status='failed',
extra_info={'error': str(e)}
)
run_task()
基于装饰器的日志记录
import logging
from functools import wraps
import time
from datetime import datetime
# 设置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - [%(task_name)s] - %(message)s',
handlers=[
logging.FileHandler('decorator_tasks.log'),
logging.StreamHandler()
]
)
def log_task(name=None):
"""任务日志装饰器"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
task_name = name or func.__name__
logger = logging.getLogger(task_name)
try:
# 开始时间
start_time = time.time()
logger.info(f"任务开始执行")
# 执行任务
result = func(*args, **kwargs)
# 完成时间
duration = time.time() - start_time
logger.info(f"任务执行完成,耗时: {duration:.2f}秒")
return result
except Exception as e:
logger.error(f"任务执行失败: {str(e)}")
raise
return wrapper
return decorator
# 使用装饰器
@log_task(name="数据同步任务")
def sync_data():
"""数据同步"""
time.sleep(2)
return "数据同步完成"
@log_task(name="邮件发送任务")
def send_emails():
"""发送邮件"""
time.sleep(1)
# raise Exception("发送失败")
return "邮件发送成功"
# 执行任务
sync_data()
send_emails()
数据库日志存储
import sqlite3
import logging
from datetime import datetime
import json
class DatabaseTaskLogger:
"""数据库日志存储"""
def __init__(self, db_path='task_logs.db'):
self.conn = sqlite3.connect(db_path)
self.cursor = self.conn.cursor()
self.create_tables()
# 设置文件日志作为补充
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
filename='task_scheduler.log'
)
self.logger = logging.getLogger('task_db')
def create_tables(self):
"""创建日志表"""
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS task_logs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task_name TEXT NOT NULL,
status TEXT NOT NULL,
start_time TIMESTAMP,
end_time TIMESTAMP,
duration REAL,
error_message TEXT,
extra_data TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
self.conn.commit()
def log_task(self, task_name, status, start_time=None, end_time=None,
duration=None, error_message=None, extra_data=None):
"""记录任务日志到数据库"""
try:
self.cursor.execute('''
INSERT INTO task_logs
(task_name, status, start_time, end_time, duration, error_message, extra_data)
VALUES (?, ?, ?, ?, ?, ?, ?)
''', (
task_name,
status,
start_time or datetime.now(),
end_time,
duration,
error_message,
json.dumps(extra_data) if extra_data else None
))
self.conn.commit()
# 同时记录到文件
self.logger.info(f"任务 {task_name} - {status}")
except Exception as e:
self.logger.error(f"数据库日志记录失败: {e}")
def get_task_history(self, task_name=None, limit=100):
"""查询任务历史"""
if task_name:
self.cursor.execute(
"SELECT * FROM task_logs WHERE task_name=? ORDER BY created_at DESC LIMIT ?",
(task_name, limit)
)
else:
self.cursor.execute(
"SELECT * FROM task_logs ORDER BY created_at DESC LIMIT ?",
(limit,)
)
return self.cursor.fetchall()
def get_statistics(self, since_days=7):
"""获取任务统计信息"""
self.cursor.execute('''
SELECT
task_name,
COUNT(*) as total_executions,
SUM(CASE WHEN status='success' THEN 1 ELSE 0 END) as success_count,
SUM(CASE WHEN status='failed' THEN 1 ELSE 0 END) as failed_count,
AVG(duration) as avg_duration
FROM task_logs
WHERE created_at >= datetime('now', '-' || ? || ' days')
GROUP BY task_name
''', (since_days,))
return self.cursor.fetchall()
def close(self):
"""关闭数据库连接"""
self.conn.close()
# 使用示例
db_logger = DatabaseTaskLogger()
# 模拟任务
def simulated_task():
start = datetime.now()
task_name = "文件清理"
try:
# 模拟任务执行
import random
time.sleep(random.uniform(1, 3))
if random.random() > 0.8: # 20%概率失败
raise Exception("模拟错误")
# 记录成功
db_logger.log_task(
task_name=task_name,
status='success',
start_time=start,
end_time=datetime.now(),
duration=time.time() - time.mktime(start.timetuple()),
extra_data={'files_cleaned': 100}
)
except Exception as e:
db_logger.log_task(
task_name=task_name,
status='failed',
start_time=start,
end_time=datetime.now(),
duration=time.time() - time.mktime(start.timetuple()),
error_message=str(e)
)
# 执行多次任务
for _ in range(5):
simulated_task()
# 查看统计信息
stats = db_logger.get_statistics()
print("任务统计:", stats)
# 关闭连接
db_logger.close()
选择建议
- 简单任务:使用基础logging模块
- 复杂调度:使用APScheduler + logging
- 需要分析:使用数据库存储日志
- 性能监控:使用装饰器 + 性能日志
选择哪种方式取决于你的具体需求,建议从简单的开始,根据需要逐步升级。