""" 日志模块 - 使用环境变量配置 """ import os import sys import threading from datetime import datetime # 日志级别定义 LOG_LEVELS = { 'debug': 0, 'info': 1, 'warning': 2, 'error': 3, 'critical': 4 } # 线程锁,用于文件写入同步 _file_lock = threading.Lock() # 文件写入状态标志 _file_writing_disabled = False _disable_reason = None def _get_current_log_level(): """获取当前日志级别""" level = os.getenv('LOG_LEVEL', 'info').lower() return LOG_LEVELS.get(level, LOG_LEVELS['info']) def _get_log_file_path(): """获取日志文件路径""" return os.getenv('LOG_FILE', 'log.txt') def _write_to_file(message: str): """线程安全地写入日志文件""" global _file_writing_disabled, _disable_reason # 如果文件写入已被禁用,直接返回 if _file_writing_disabled: return try: log_file = _get_log_file_path() with _file_lock: with open(log_file, 'a', encoding='utf-8') as f: f.write(message + '\n') f.flush() # 强制刷新到磁盘,确保实时写入 except (PermissionError, OSError, IOError) as e: # 检测只读文件系统或权限问题,禁用文件写入 _file_writing_disabled = True _disable_reason = str(e) print(f"Warning: File system appears to be read-only or permission denied. Disabling log file writing: {e}", file=sys.stderr) print(f"Log messages will continue to display in console only.", file=sys.stderr) except Exception as e: # 其他异常仍然输出警告但不禁用写入(可能是临时问题) print(f"Warning: Failed to write to log file: {e}", file=sys.stderr) def _log(level: str, message: str): """ 内部日志函数 """ level = level.lower() if level not in LOG_LEVELS: print(f"Warning: Unknown log level '{level}'", file=sys.stderr) return # 检查日志级别 current_level = _get_current_log_level() if LOG_LEVELS[level] < current_level: return # 格式化日志消息 timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") entry = f"[{timestamp}] [{level.upper()}] {message}" # 输出到控制台 if level in ('error', 'critical'): print(entry, file=sys.stderr) else: print(entry) # 实时写入文件 _write_to_file(entry) def set_log_level(level: str): """设置日志级别提示""" level = level.lower() if level not in LOG_LEVELS: print(f"Warning: Unknown log level '{level}'. Valid levels: {', '.join(LOG_LEVELS.keys())}") return False print(f"Note: To set log level '{level}', please set LOG_LEVEL environment variable") return True class Logger: """支持 log('info', 'msg') 和 log.info('msg') 两种调用方式""" def __call__(self, level: str, message: str): """支持 log('info', 'message') 调用方式""" _log(level, message) def debug(self, message: str): """记录调试信息""" _log('debug', message) def info(self, message: str): """记录一般信息""" _log('info', message) def warning(self, message: str): """记录警告信息""" _log('warning', message) def error(self, message: str): """记录错误信息""" _log('error', message) def critical(self, message: str): """记录严重错误信息""" _log('critical', message) def get_current_level(self) -> str: """获取当前日志级别名称""" current_level = _get_current_log_level() for name, value in LOG_LEVELS.items(): if value == current_level: return name return 'info' def get_log_file(self) -> str: """获取当前日志文件路径""" return _get_log_file_path() # 导出全局日志实例 log = Logger() # 导出的公共接口 __all__ = ['log', 'set_log_level', 'LOG_LEVELS'] # 使用说明: # 1. 设置日志级别: export LOG_LEVEL=debug (或在.env文件中设置) # 2. 设置日志文件: export LOG_FILE=log.txt (或在.env文件中设置)