在Python项目中统一处理日志
在Python项目中统一处理日志是个很好的实践,有助于调试、监控和问题追踪。下面介绍如何在你的项目中实现统一的日志配置。
1. 日志配置方案
推荐使用logging
模块并通过配置文件管理日志设置,这样可以灵活调整日志级别、输出格式和处理方式。
首先在项目中创建logging_config.py
文件:
# src/my_package/logging_config.py
import logging
import logging.config
import os
from typing import Dictdef get_logger_config(log_dir: str = None) -> Dict:"""生成日志配置"""# 如果指定了日志目录,确保目录存在if log_dir:os.makedirs(log_dir, exist_ok=True)config = {'version': 1,'disable_existing_loggers': False,'formatters': {'standard': {'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s'},'detailed': {'format': '%(asctime)s - %(name)s - %(levelname)s - %(module)s:%(lineno)d - %(message)s'},},'handlers': {'console': {'class': 'logging.StreamHandler','formatter': 'standard','level': 'INFO','stream': 'ext://sys.stdout',},},'loggers': {'': { # 根logger'handlers': ['console'],'level': 'INFO','propagate': True,},'my_package': { # 项目主包的logger'handlers': ['console'],'level': 'DEBUG','propagate': False,},},}# 如果指定了日志目录,添加文件处理器if log_dir:config['handlers']['file'] = {'class': 'logging.handlers.RotatingFileHandler','formatter': 'detailed','level': 'DEBUG','filename': os.path.join(log_dir, 'app.log'),'maxBytes': 10 * 1024 * 1024, # 10 MB'backupCount': 5,}# 更新logger配置,同时输出到控制台和文件for logger in config['loggers'].values():if 'console' in logger['handlers']:logger['handlers'].append('file')return configdef setup_logging(log_dir: str = None):"""配置并初始化日志系统"""config = get_logger_config(log_dir)logging.config.dictConfig(config)
2. 在主程序中初始化日志
在项目入口文件中初始化日志配置:
# src/my_package/main.py
import os
from .logging_config import setup_logging# 配置日志(可选指定日志文件目录)
log_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../logs')
setup_logging(log_dir)# 获取logger
logger = logging.getLogger(__name__)def main():logger.info("应用启动")# 主程序逻辑logger.debug("执行主程序逻辑")# ...if __name__ == "__main__":main()
3. 在模块中使用日志
在其他模块中直接获取logger即可使用:
# src/my_package/utils.py
import logging# 获取当前模块的logger
logger = logging.getLogger(__name__)def some_function():logger.debug("进入函数 some_function")try:# 函数逻辑logger.info("函数执行成功")except Exception as e:logger.error("函数执行出错: %s", str(e), exc_info=True)
4. 日志配置增强
可以通过环境变量灵活控制日志行为:
# src/my_package/logging_config.py
import osdef get_logger_config():# ... 原有配置代码 ...# 根据环境变量调整日志级别log_level = os.getenv('LOG_LEVEL', 'INFO').upper()config['loggers']['']['level'] = log_levelconfig['loggers']['my_package']['level'] = log_level# ... 其余配置代码 ...
这样可以通过设置环境变量来控制日志级别:
LOG_LEVEL=DEBUG python src/my_package/main.py
5. 日志最佳实践
-
使用模块名作为logger名称:
logger = logging.getLogger(__name__)
-
使用适当的日志级别:
- DEBUG: 详细的调试信息
- INFO: 确认程序按预期运行
- WARNING: 潜在问题
- ERROR: 发生错误但程序仍可继续运行
- CRITICAL: 严重错误,程序无法继续运行
-
结构化日志(可选):
如果需要更强大的日志分析能力,可以使用structlog
库实现结构化日志:pip install structlog
配置示例:
# src/my_package/logging_config.py import structlogdef setup_structured_logging():structlog.configure(processors=[structlog.stdlib.add_log_level,structlog.stdlib.PositionalArgumentsFormatter(),structlog.processors.TimeStamper(fmt="iso"),structlog.processors.JSONRenderer(),],logger_factory=structlog.stdlib.LoggerFactory(),)
通过以上配置,你的项目将拥有统一的日志系统,便于调试和监控。所有日志格式、存储位置和级别都可以在一个地方集中管理。