You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python日志统一写入指定目录单个文件问题求助

Fix: Write All Class Logs to a Single File in the Specified Logs Directory

Let's break down why your current code is creating separate log files per class, then fix it to route all logs to one file in the Logs directory.

The Root Cause

Your exception handler is generating a log file named after each class (%s.log" % self.__class__.__name__), which means every class that hits this branch creates its own unique log file. Plus, you weren't setting a global shared log file path upfront, so each class ends up initializing its own separate file handler.

Step-by-Step Fix

We'll ensure all classes use the same log file, set up the Logs directory safely, and avoid redundant code.

1. First: Initialize a Global Shared Log File

Add this code somewhere at the start of your application (e.g., main entry point, before any class initializes its logger):

import os
import logging
from your_module import PyLog  # Replace with your actual PyLog module path

# Create Logs directory (no error if it already exists)
log_dir = os.path.join(os.getcwd(), "Logs")
os.makedirs(log_dir, exist_ok=True)

# Define a single shared log file path
global_log_file = os.path.join(log_dir, "app.log")  # You can rename this to something like "all_classes.log"

# Set this as a class-level attribute on PyLog so all classes can use it
PyLog.log_file = global_log_file

2. Simplify Logger Initialization in Your Classes

Now every class can safely use the global log file without hitting the exception branch (unless something goes wrong). Update your logger setup in xyz and abc classes to:

logger = PyLog().get_logger(self.__class__.__name__, getattr(PyLog, "log_file"), logging.INFO)

3. Fallback Logic (Optional but Robust)

If you still want to keep the exception handler as a safety net (in case the global log file isn't initialized), modify it to use the shared log file instead of class-specific ones:

try:
    logger = PyLog().get_logger(self.__class__.__name__, getattr(PyLog, "log_file"), logging.INFO)
except AttributeError:
    # Create Logs directory safely
    log_dir = os.path.join(os.getcwd(), "Logs")
    os.makedirs(log_dir, exist_ok=True)
    # Use a single shared log file
    global_log_file = os.path.join(log_dir, "app.log")
    # Set the global attribute so future classes don't hit this branch
    PyLog.log_file = global_log_file
    # Initialize logger with the shared file
    logger = PyLog().get_logger(self.__class__.__name__, global_log_file, logging.INFO)

4. Bonus: Clean Up Redundant Code in PyLog

Your create_log_handler and get_logger methods have identical handler setup logic. Let's refactor to avoid duplication:

import logging
import datetime
import time

class PyLog():
    # Extract shared handler setup logic into a helper method
    def _setup_log_handler(self, logger, log_file, log_level):
        if not getattr(logger, 'handler_set', None):
            fileh = logging.FileHandler(log_file)
            fh_format = logging.Formatter('%(asctime)s - %(name)s:%(lineno)d - %(levelname)s - %(message)s')
            fileh.setFormatter(fh_format)
            logger.addHandler(fileh)
            
            if log_level is not None:
                logger.setLevel(log_level)
                fileh.setLevel(log_level)
            
            logger.handler_set = True

    def create_log_handler(self, module, log_file, log_level=None):
        logger = logging.getLogger(module)
        self._setup_log_handler(logger, log_file, log_level)
        setattr(PyLog, 'log_file', log_file)
        setattr(PyLog, 'logger', logger)
        return logger

    def get_logger(self, module, log_file, log_level=None, set_attr=False):
        logger = logging.getLogger(module)
        self._setup_log_handler(logger, log_file, log_level)
        if set_attr:
            setattr(PyLog, 'log_file', log_file)
            setattr(PyLog, 'logger', logger)
        return logger

    @staticmethod
    def write_log(logger_method, log_msg):
        log_msg = str(log_msg)
        print(f"{logger_method}: {log_msg}")
        logger_method(log_msg)

    @staticmethod
    def getTimeStamp():
        return datetime.fromtimestamp(time.time()).strftime('%Y%m%d%H%M%S')

How It Works Now

  • All classes will use the same app.log file in the Logs directory.
  • The handler_set flag ensures we don't add duplicate handlers to the logger (which would cause duplicate log entries).
  • The global PyLog.log_file attribute ensures every class references the same file path once initialized.

内容的提问来源于stack exchange,提问作者cool_viju

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:17:49