Files
update_day/log_style.py
lintaogood d02856fa5c feat: 添加市场数据检查脚本和日志配置模块
添加 check_market_data.py 脚本用于检查行情数据完整性
实现 Tushare API 管理、交易日历缓存和在线数据检查功能
添加 log_style.py 模块提供灵活的日志配置功能
创建相关批处理文件和日志文件
2025-12-05 23:04:32 +08:00

198 lines
5.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""
日志配置模块
提供灵活的日志系统配置功能
"""
import logging
import os
import sys
from logging.handlers import TimedRotatingFileHandler
from datetime import datetime
# 默认日志配置
DEFAULT_LOG_FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
DEFAULT_DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
DEFAULT_LOG_LEVEL = logging.INFO
# 全局日志记录器缓存
_loggers = {}
def setup_logger(
name='backtrader',
log_file=None,
level=DEFAULT_LOG_LEVEL,
log_format=DEFAULT_LOG_FORMAT,
date_format=DEFAULT_DATE_FORMAT,
console=True,
file_level=None,
log_dir='logs',
backup_count=7
):
"""
配置日志记录器
Args:
name: 日志记录器名称
log_file: 日志文件路径如果为None则自动生成
level: 日志级别
log_format: 日志格式
date_format: 日期格式
console: 是否输出到控制台
file_level: 文件日志级别如果为None则使用level
log_dir: 日志文件目录
backup_count: 日志文件保留数量
Returns:
logging.Logger: 配置好的日志记录器
"""
# 如果日志记录器已存在,则直接返回
if name in _loggers:
return _loggers[name]
# 创建日志记录器
logger = logging.getLogger(name)
logger.setLevel(level)
# 避免重复添加处理器
if logger.handlers:
logger.handlers.clear()
# 创建格式化器
formatter = logging.Formatter(log_format, datefmt=date_format)
# 添加控制台处理器
if console:
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(level)
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
# 添加文件处理器
if log_file or log_dir:
# 确保日志目录存在
if log_dir and not os.path.exists(log_dir):
try:
os.makedirs(log_dir)
except Exception as e:
logger.error(f'创建日志目录失败: {str(e)}')
# 生成日志文件名
if not log_file:
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
log_file = os.path.join(log_dir, f'{name}_{timestamp}.log')
# 使用TimedRotatingFileHandler实现按时间轮换
try:
file_handler = TimedRotatingFileHandler(
log_file,
when='midnight',
interval=1,
backupCount=backup_count,
encoding='utf-8'
)
# 设置文件日志级别
file_handler.setLevel(file_level or level)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
logger.info(f'日志文件已配置: {log_file}')
except Exception as e:
logger.error(f'配置日志文件失败: {str(e)}')
# 保存到缓存
_loggers[name] = logger
return logger
def get_logger(name='backtrader'):
"""
获取日志记录器
Args:
name: 日志记录器名称
Returns:
logging.Logger: 日志记录器
"""
if name not in _loggers:
# 如果日志记录器不存在,则创建默认配置的日志记录器
return setup_logger(name)
return _loggers[name]
def set_global_level(level):
"""
设置所有已创建日志记录器的全局级别
Args:
level: 日志级别
"""
for logger_name, logger in _loggers.items():
logger.setLevel(level)
# 设置所有处理器的级别
for handler in logger.handlers:
handler.setLevel(level)
def shutdown_loggers():
"""
关闭所有日志记录器
"""
logging.shutdown()
_loggers.clear()
def log_exception(logger_name='backtrader', message='发生异常', exc_info=True):
"""
记录异常信息
Args:
logger_name: 日志记录器名称
message: 异常消息
exc_info: 是否记录异常堆栈信息
"""
logger = get_logger(logger_name)
logger.error(message, exc_info=exc_info)
def create_specialized_logger(
name,
log_file=None,
level=DEFAULT_LOG_LEVEL,
console=True,
**kwargs
):
"""
创建专门用途的日志记录器
Args:
name: 日志记录器名称
log_file: 日志文件路径
level: 日志级别
console: 是否输出到控制台
**kwargs: 其他参数
Returns:
logging.Logger: 配置好的日志记录器
"""
# 构建专用日志格式
specialized_format = kwargs.get(
'log_format',
f'[%(asctime)s] [{name.upper()}] [%(levelname)s] %(message)s'
)
return setup_logger(
name=name,
log_file=log_file,
level=level,
log_format=specialized_format,
console=console,
**kwargs
)