From d8a423c983b28adf514ee4774f8a7e74f41d7f80 Mon Sep 17 00:00:00 2001 From: Misaka_Company Date: Wed, 15 Jul 2026 14:29:00 +0800 Subject: [PATCH] fix: make setup_logging idempotent to avoid duplicate log lines setup_logging unconditionally addHandler'd on every call. Under the new main.py entry the function was invoked twice for --loop mode (main.py and service.run both called it), stacking two file + two console handlers so every log line was written twice. Clear any pre-existing root handlers before re-adding so repeated calls always yield exactly one file handler + one console handler, regardless of the caller. Preserves the standalone python -m sync.service entry point. --- src/sync/logging_setup.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/sync/logging_setup.py b/src/sync/logging_setup.py index 7ca32f9..3186857 100644 --- a/src/sync/logging_setup.py +++ b/src/sync/logging_setup.py @@ -18,12 +18,26 @@ def setup_logging(cfg_dict: dict | None): level = getattr(logging, (cfg_dict or {}).get("level", "INFO")) if cfg_dict else logging.INFO path = (cfg_dict or {}).get("path", "sync.log") os.makedirs(os.path.dirname(path) or ".", exist_ok=True) + + # Idempotent: drop any handlers already attached to the root logger before + # re-adding. setup_logging can be called from more than one entry point + # (e.g. main.py and service.run), and the old code unconditionally + # addHandler'd each time, stacking duplicate handlers so every log line was + # written twice. Clearing first means repeated calls always yield exactly + # one file handler + one console handler, regardless of caller. + root = logging.getLogger() + for old in list(root.handlers): + root.removeHandler(old) + try: + old.close() + except Exception: + pass + root.setLevel(level) + h = logging.handlers.RotatingFileHandler( path, maxBytes=10 * 1024 * 1024, backupCount=5, encoding="utf-8" ) h.setFormatter(logging.Formatter("%(asctime)s %(levelname)s [%(name)s] %(message)s")) - root = logging.getLogger() - root.setLevel(level) root.addHandler(h) sh = logging.StreamHandler() sh.setFormatter(logging.Formatter("%(levelname)s %(message)s"))