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.
This commit is contained in:
Misaka_Company
2026-07-15 14:29:00 +08:00
parent 7d11eddc7a
commit d8a423c983

View File

@@ -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"))