Python 日志记录未创建日志文件的多个实例

Python logging is not creating multiple instance of log files

我正在尝试创建一个 class,它可以使用已保存的 .log.

创建多个日志记录实例

这是我的代码:

import logging
from datetime import datetime
import sys
import os


class DummyLog:
    def __init__(self,
                 log_name: str = datetime.now().strftime('%d_%m_%Y__%H_%M_%S'),
                 logging_level: str = 'debug',
                 string_format: str = '%(asctime)s: %(levelname)s: %(message)s',
                 datetime_format: str = '%m/%d/%Y %I:%M:%S %p',
                 log_on_folder: bool = True,
                 log_folder_name: str = 'logs'
                 ):
        self.logName = log_name
        self.logger = None
        self.loggingLevel = logging_level
        self.stringFormat = string_format
        self.datetimeFormat = datetime_format

        if log_on_folder:
            if not os.path.exists(log_folder_name):
                os.mkdir(log_folder_name)
            self.logName = log_folder_name + '/' + self.logName

        self.initiateLogger()

    def initiateLogger(self):
        """ This function will initiate the logger as a single threaded log"""

        self.logger = logging.getLogger(self.logName)
        if self.loggingLevel == 'debug':
            self.loggingLevel = logging.DEBUG
        self.logger.setLevel(self.loggingLevel)
        logFormat = logging.Formatter(self.stringFormat, datefmt=self.datetimeFormat)

        # Creating and adding the console handler
        consoleHandler = logging.StreamHandler(sys.stdout)
        consoleHandler.setFormatter(logFormat)
        self.logger.addHandler(consoleHandler)

        # Creating and adding the file handler
        fileHandler = logging.FileHandler(self.logName + ".log", mode='w')
        fileHandler.setFormatter(logFormat)
        self.logger.addHandler(fileHandler)


dl = DummyLog()
dl.logger.info("hi")

import time
time.sleep(1)

dl1 = DummyLog()
dl1.logger.info("hi")

当我 运行 上面的代码时,它只创建一个 .log 文件并且 dldl1 对象都被记录在同一个 .log 文件.

控制台输出打印 log 3 次而不是 2 次:

01/03/2022 12:01:20 PM: INFO: hi
01/03/2022 12:01:21 PM: INFO: hi
01/03/2022 12:01:21 PM: INFO: hi

但我已经启动了两次class Dummylog。我期待代码更改,其中 class DummyLog 可以在多个实例中调用,每个实例将保存一个单独的 .log 文件。

我知道我在 Handler 中遗漏了一些东西,但没有任何东西可以帮助我完成所需的更改。

任何帮助将不胜感激!!

您的默认日志名称基于时间,但准确性次之,您必须在记录器实例之间放置 sleep 或使用非默认名称:

dl = DummyLog(log_name="name1")
dl.logger.info("hi")

import time
time.sleep(1)

dl1 = DummyLog(log_name="name2")
dl1.logger.info("hi")

结果将是

logs
├── name1.log
└── name2.log

我发现你的代码存在主要问题,你在默认参数中使用了函数调用:

log_name: str = datetime.now().strftime('%d_%m_%Y__%H_%M_%S'),

由此 lang_name 在 Class 定义时使用字符串启动并且从未更改。 您可以使用这样的解决方案:

import logging
from datetime import datetime
import sys
import os


class DummyLog:
    counter = 0
    def __init__(self,
                 log_name: str = "",
                 logging_level: str = 'debug',
                 string_format: str = '%(asctime)s: %(levelname)s: %(message)s',
                 datetime_format: str = '%m/%d/%Y %I:%M:%S %p',
                 log_on_folder: bool = True,
                 log_folder_name: str = 'logs'
                 ):
        if log_name:
            self.logName = log_name
        else:
            self.logName = f"{DummyLog.counter}_{datetime.now().strftime('%d_%m_%Y__%H_%M_%S')}"
        DummyLog.counter += 1
        self.logger = None
        self.loggingLevel = logging_level
        self.stringFormat = string_format
        self.datetimeFormat = datetime_format

        if log_on_folder:
            if not os.path.exists(log_folder_name):
                os.mkdir(log_folder_name)
            self.logName = log_folder_name + '/' + self.logName

        self.initiateLogger()

    def initiateLogger(self):
        """ This function will initiate the logger as a single threaded log"""

        self.logger = logging.getLogger(self.logName)
        if self.loggingLevel == 'debug':
            self.loggingLevel = logging.DEBUG
        self.logger.setLevel(self.loggingLevel)
        logFormat = logging.Formatter(self.stringFormat, datefmt=self.datetimeFormat)

        # Creating and adding the console handler
        consoleHandler = logging.StreamHandler(sys.stdout)
        consoleHandler.setFormatter(logFormat)
        self.logger.addHandler(consoleHandler)

        # Creating and adding the file handler
        fileHandler = logging.FileHandler(self.logName + ".log", mode='w')
        fileHandler.setFormatter(logFormat)
        self.logger.addHandler(fileHandler)


dl = DummyLog()
dl.logger.info("hi dl")

dl1 = DummyLog()
dl1.logger.info("hi dl1")

dl2 = DummyLog()
dl2.logger.info("hi dl2")

不要使用mutable objects as default parameters。相反,在运行时传递它们或使用 None 作为默认值并设置值。

在您的情况下,DateTime 是在函数定义时计算的。

例如:

def __init__(self,
             log_name = None,
             logging_level: str = 'debug',
             string_format: str = '%(asctime)s: %(levelname)s: %(message)s',
             datetime_format: str = '%m/%d/%Y %I:%M:%S %p',
             log_on_folder: bool = True,
             log_folder_name: str = 'logs'
             ):
    if log_name is None:
      self.logName = datetime.now().strftime('%d_%m_%Y__%H_%M_%S')

dl = DummyLog()
dl.logger.info("hi")

import time
time.sleep(1)

dl1 = DummyLog()
dl1.logger.info("hi")

或在运行时传递。

dl = DummyLog(log_name=datetime.now().strftime('%d_%m_%Y__%H_%M_%S'))
dl.logger.info("hi")

import time
time.sleep(1)

dl1 = DummyLog(log_name=datetime.now().strftime('%d_%m_%Y__%H_%M_%S'))
dl1.logger.info("hi")

感谢@S4eed3sm 的回答。我正在更新创建多个 .log 文件并使用 datetime.now().strftime('%d_%m_%Y__%H_%M_%S') 创建日志并带有前缀

的答案
import logging
from datetime import datetime
import sys
import os


class DummyLog:
    def __init__(self,
                 log_name: str = datetime.now().strftime('%d_%m_%Y__%H_%M_%S'),
                 logging_level: str = 'debug',
                 string_format: str = '%(asctime)s: %(levelname)s: %(message)s',
                 datetime_format: str = '%m/%d/%Y %I:%M:%S %p',
                 log_on_folder: bool = True,
                 log_folder_name: str = 'logs',
                 log_prefix: str = None
                 ):
        if log_prefix:
            self.logName = log_prefix + log_name
        else:
            self.logName = log_name
        self.logger = None
        self.loggingLevel = logging_level
        self.stringFormat = string_format
        self.datetimeFormat = datetime_format

        if log_on_folder:
            if not os.path.exists(log_folder_name):
                os.mkdir(log_folder_name)
            self.logName = log_folder_name + '/' + self.logName

        self.initiateLogger()

    def initiateLogger(self):
        """ This function will initiate the logger as a single threaded log"""

        self.logger = logging.getLogger(self.logName)
        if self.loggingLevel == 'debug':
            self.loggingLevel = logging.DEBUG
        self.logger.setLevel(self.loggingLevel)
        logFormat = logging.Formatter(self.stringFormat, datefmt=self.datetimeFormat)

        # Creating and adding the console handler
        consoleHandler = logging.StreamHandler(sys.stdout)
        consoleHandler.setFormatter(logFormat)
        self.logger.addHandler(consoleHandler)

        # Creating and adding the file handler
        fileHandler = logging.FileHandler(self.logName + ".log", mode='w')
        fileHandler.setFormatter(logFormat)
        self.logger.addHandler(fileHandler)


dl = DummyLog(log_prefix='one_')
dl.logger.info("hi")

dl1 = DummyLog(log_prefix='two_')
dl1.logger.info("hi")

这将创建多个具有以下前缀的 .logs

logs
├── one_03_01_2022__12_42_02.log
└── two_03_01_2022__12_42_02.log