import logging import os import sys import io def _log_path(): # Mirror config.get_data_root() without importing config (avoids a circular # import, since config imports this module). The desktop build sets # COW_DATA_DIR (e.g. ~/.cow); source deployments fall back to CWD. data_dir = os.environ.get("COW_DATA_DIR") if data_dir: data_dir = os.path.expanduser(data_dir) os.makedirs(data_dir, exist_ok=True) return os.path.join(data_dir, "run.log") return "run.log" def _reset_logger(log): for handler in log.handlers: handler.close() log.removeHandler(handler) del handler log.handlers.clear() log.propagate = False stdout = sys.stdout if hasattr(stdout, "buffer"): stdout = io.TextIOWrapper(stdout.buffer, encoding="utf-8", errors="replace", line_buffering=True) console_handle = logging.StreamHandler(stdout) console_handle.setFormatter( logging.Formatter( "[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d] - %(message)s", datefmt="%Y-%m-%d %H:%M:%S", ) ) file_handle = logging.FileHandler(_log_path(), encoding="utf-8") file_handle.setFormatter( logging.Formatter( "[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d] - %(message)s", datefmt="%Y-%m-%d %H:%M:%S", ) ) log.addHandler(file_handle) log.addHandler(console_handle) def _get_logger(): log = logging.getLogger("log") _reset_logger(log) log.setLevel(logging.INFO) return log # 日志句柄 logger = _get_logger()