Files
geo_tools/app/utils/logger.py
missum db51d41aef refactor: 重构项目结构,将geo_tools重命名为app并更新相关引用
- 将主包名从geo_tools改为app
- 更新所有模块中的引用路径
- 迁移并更新测试用例
- 添加项目规则文档
- 保持原有功能不变,仅进行结构调整
2026-04-12 19:49:56 +08:00

108 lines
3.2 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.
"""
geo_tools.utils.logger
~~~~~~~~~~~~~~~~~~~~~~
统一日志工厂,支持同时输出到控制台和文件。
使用方式
--------
>>> from geo_tools.utils.logger import get_logger
>>> logger = get_logger(__name__)
>>> logger.info("处理开始")
"""
from __future__ import annotations
import logging
import sys
from pathlib import Path
_LOG_FORMAT = "%(asctime)s | %(levelname)-8s | %(name)s | %(message)s"
_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
# 已初始化的 logger 集合,避免重复添加 handler
_initialized: set[str] = set()
def get_logger(
name: str,
level: str | None = None,
log_file: Path | str | None = None,
*,
propagate: bool = False,
) -> logging.Logger:
"""获取(或创建)一个带格式化 handler 的 Logger。
Parameters
----------
name:
Logger 名称,通常传入 ``__name__``。
level:
日志等级字符串;``None`` 时读取 ``settings.log_level``。
log_file:
日志文件路径;``None`` 时读取 ``settings``
若 ``settings.log_to_file`` 为 True则写到 ``settings.log_dir/geo_tools.log``。
propagate:
是否向父 logger 传播,默认 False避免重复输出
Returns
-------
logging.Logger
"""
# 延迟导入,避免循环依赖
from app.config.settings import settings as _settings
if level is None:
level = _settings.log_level
numeric_level = logging.getLevelName(level.upper())
logger = logging.getLogger(name)
logger.propagate = propagate
# 已初始化则直接返回level 可动态调整
if name in _initialized:
logger.setLevel(numeric_level)
return logger
logger.setLevel(numeric_level)
formatter = logging.Formatter(_LOG_FORMAT, datefmt=_DATE_FORMAT)
# ── 控制台 handler ────────────────────────────────────────
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(numeric_level)
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
# ── 文件 handler ──────────────────────────────────────────
_resolve_log_file = log_file
if _resolve_log_file is None and _settings.log_to_file:
_settings.ensure_dirs()
_resolve_log_file = _settings.log_dir / "geo_tools.log"
if _resolve_log_file is not None:
file_path = Path(_resolve_log_file)
file_path.parent.mkdir(parents=True, exist_ok=True)
file_handler = logging.FileHandler(file_path, encoding="utf-8")
file_handler.setLevel(numeric_level)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
_initialized.add(name)
return logger
def set_global_level(level: str) -> None:
"""动态调整所有 geo_tools 下 logger 的日志等级。
Parameters
----------
level:
目标日志等级,例如 ``"DEBUG"``。
"""
numeric = logging.getLevelName(level.upper())
root = logging.getLogger("geo_tools")
root.setLevel(numeric)
for handler in root.handlers:
handler.setLevel(numeric)