Python日志统一写入指定目录单个文件问题求助
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.logfile in theLogsdirectory. - The
handler_setflag ensures we don't add duplicate handlers to the logger (which would cause duplicate log entries). - The global
PyLog.log_fileattribute ensures every class references the same file path once initialized.
内容的提问来源于stack exchange,提问作者cool_viju

