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
文件并且 dl
和 dl1
对象都被记录在同一个 .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")
这将创建多个具有以下前缀的 .log
s
logs
├── one_03_01_2022__12_42_02.log
└── two_03_01_2022__12_42_02.log
我正在尝试创建一个 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
文件并且 dl
和 dl1
对象都被记录在同一个 .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")
这将创建多个具有以下前缀的 .log
s
logs
├── one_03_01_2022__12_42_02.log
└── two_03_01_2022__12_42_02.log