简体   繁体   English

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

[英]Python logging is not creating multiple instance of log files

I am trying to create a class that can create multiple instances of logging with saved .log .我正在尝试创建一个class ,它可以使用已保存的.log创建多个日志记录实例。

This is my code:这是我的代码:

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

When I run the above code, it creates only one .log file and both the dl and dl1 objects are being logged on the same .log file.当我运行上面的代码时,它只创建一个.log文件,并且dldl1对象都记录在同一个.log文件上。

The console output is printing the log 3 times instead of 2 times:控制台 output 打印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

but I have initiated the class Dummylog two times.但我已经启动了class Dummylog I am expecting the code change where the class DummyLog can be called at multiple instances and each instance will save an individual .log file.我期待可以在多个实例中调用class DummyLog的代码更改,并且每个实例将保存一个单独的.log文件。

I know I am missing something in the Handler , but nothing is helping me to come over the required change.我知道我在Handler中遗漏了一些东西,但没有什么能帮助我完成所需的更改。

Any help will be appreciated !!任何帮助将不胜感激 !!

Your default log name is based on time, but accuracy is second you must put sleep between logger instance or use non-default names:您的默认日志名称基于时间,但准确性次之,您必须在记录器实例之间设置睡眠或使用非默认名称:

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

import time
time.sleep(1)

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

and the result will be结果将是

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

I found your code main issue, you use a function call in your default argument:我发现了您的代码主要问题,您在默认参数中使用了 function 调用:

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

by this lang_name initiate with a string at Class definition time and never changed.通过这个lang_name在 Class 定义时间用一个字符串启动并且永远不会改变。 You could use solution like this:您可以使用这样的解决方案:

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

Do not use mutable objects as default parameters .不要使用可变对象作为默认参数 Instead, pass them in runtime or use None as default and set the value.相反,在运行时传递它们或使用 None 作为默认值并设置值。

In your case DateTime is evaluated at function definition time.在您的情况下, DateTime 在 function 定义时间进行评估。

Ex:前任:

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

OR pass in runtime.或在运行时传递。

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

Thanks to @S4eed3sm for the Answer.感谢@S4eed3sm 的回答。 I am updating the Answer which creates multiple .log files and uses datetime.now().strftime('%d_%m_%Y__%H_%M_%S') to create a log and have a prefix with it我正在更新创建多个.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")

This will create multiple .log s with prefixes below这将创建多个带有以下前缀的.log

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM