[英]Two writes using python logging
I have two files of classes with essentially the same set up of logging: 我有两个类的文件,它们的日志设置基本相同:
"""code - of 1 class the parent with mods from Reut's answer"""
logger = None
def __init__(self, verboseLevel=4):
'''
Constructor
'''
loggingLevels={1: logging.DEBUG,
2: logging.INFO,
3: logging.WARNING,
4: logging.ERROR,
5: logging.CRITICAL}
#debug(), info(), warning(), error(), critical()
if not tdoa.logger:
tdoa.logger=logging.getLogger('TDOA')
if (verboseLevel in range(1,6)):
logging.basicConfig(format='%(message)s',level=loggingLevels[verboseLevel])
else:
logging.basicConfig(format='%(levelname)s:%(message)s',level=logging.DEBUG)
tdoa.logger.critical("Incorrect logging level specified!")
self.logger = tdoa.logger
self.logger.debug("TDOA calculator using Newton's method.")
self.verboseLevel = verboseLevel
"""code of second "subclass" (with Reut's changes) (who's function is printing twice):"""
def __init__(self, verboseLevel=1, numberOfBytes=2, filename='myfile.log', ipaddr='127.0.0.1',getelset= True):
#debug(), info(), warning(), error(), critical()
# go through all this to know that only one logger is instantiated per class
# Set debug level
# set up various handlers (remove Std_err one for deployment unless you want them going to screen
# create console handler with a higher log level
if not capture.logger:
capture.logger=logging.getLogger('SatGeo')
console = logging.StreamHandler()
if (verboseLevel in range(1,6)):
console.setLevel(self.loggingLevels[verboseLevel])
logging.basicConfig(format='%(message)s',level=self.loggingLevels[verboseLevel],
filename=filename,filemode='a') #format='%(levelname)s:%(message)s'
else:
logging.basicConfig(format='%(message)s',level=logging.DEBUG,
filename=filename,filemod='a')
console.setLevel(logging.DEBUG)
capture.logger.critical("Incorrect logging level specified!")
# create formatter and add it to the handlers
#formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
#console.setFormatter(formatter)
# add the handlers to logger
handlers=capture.logger.handlers
if (console not in handlers):
capture.logger.addHandler(console)
else:
capture.logger.critical("not adding handler")
self.logger=capture.logger
I have a function in the "called class (satgeo)" that 'writes' to the logger: 我在“称为类(satgeo)”中有一个功能,可以“写入”记录器:
def printMyself(self, rowDict):
ii=1
for res in rowDict:
self.logger.critical('{0}************************************'.format(ii))
ii+=1
for key, value in res.items():
self.logger.critical(' Name: {0}\t\t Value:{1}'.format(key, value))
When I call it by itself I get one output per self.logger
call; 当我自己调用它时,每个
self.logger
调用都会得到一个输出; but when I call it from the tdoa class it writes TWICE: for example: 但是当我从tdoa类调用它时,它写了TWICE:例如:
Name: actualLat Value:36.455444
Name: actualLat Value:36.455444
Any idea of how to fix this? 关于如何解决这个问题的任何想法?
You are adding a handler to the parent class each time you construct a class instance using this line: 每次使用此行构造类实例时,您都将向父类添加一个处理程序:
self.logger.addHandler(console)
So if you do something like: 因此,如果您执行以下操作:
for _ in range(x):
SubClass1()
some_operation_with_logging()
You should be seeing x
messages, since you just added x
handlers to the logger by doing x
calls to parent's __init__
. 您应该会看到
x
消息,因为您刚刚通过对父级的__init__
进行x
调用而将x
处理程序添加到了记录器中。
You don't want to be doing that, make sure you add a handler only once ! 您不想这样做,请确保仅添加一次处理程序! You can access a logger's list of handlers using:
logger.handlers
. 您可以使用
logger.handlers
访问记录器的处理程序列表。
Also, if you're using the same logger in both classes (named "TDOA"
) by using this line in both: 另外, 如果您在两个类中都使用同一记录器(名为
"TDOA"
), 则在两个类中都使用此行:
self.logger=logging.getLogger('TDOA')
Make sure you either synchronize the logger instantiation, or use separate loggers. 确保同步记录器实例化,或使用单独的记录器。
Instead of having a private logger for each instance, you probably want a logger for all of them, or to be more precise - for the class itself: 您可能希望为所有实例创建一个记录器,或者更确切地说-为类本身创建一个记录器,而不是为每个实例都提供一个私有记录器:
class ClassWithLogger(object):
logger = None
def __init__(self):
if not ClassWithLogger.logger:
ClassWithLogger.logger = logging.getLogger("ClassWithLogger")
ClassWithLogger.logger.addHandler(logging.StreamHandler())
# log using ClassWithLogger.logger ...
# convenience:
self.logger = ClassWithLogger.logger
And now you know logger
is instantiated once per class (instead of once per instance), and all instances of a certain class use the same logger. 现在,您知道
logger
每个类实例化一次 (而不是每个实例一次),并且某个类的所有实例都使用同一记录器。
I have since found a few links suggesting that submodules should take a logger as an input during the init : 此后,我发现了一些链接,这些链接建议子模块在初始化期间应将记录器作为输入:
def __init__ (self, pattern= None, action=None, logger = None):
# Set up logging for the class
self.log = logger or logging.getLogger(__name__)
self.log.addHandler(logging.NullHandler())
Note: the nullhandler is added to avoid a warning if the user decides to not provide a logger. 注意:添加了nullhandler以避免在用户决定不提供记录器时发出警告。
Then, if you want to debug your submodule: 然后,如果要调试子模块:
if __name__ == "__main__":
log_level = logging.INFO
log = logging.getLogger('cmdparser')
log.setLevel(log_level)
fh = logging.FileHandler('cmdparser.log')
fh.setLevel(log_level)
# create console handler with a higher log level
ch = logging.StreamHandler()
ch.setLevel(log_level)
# create formatter and add it to the handlers
# formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
formatter = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
# add the handlers to the logger
log.addHandler(fh)
log.addHandler(ch)
<myfunction>(pattern,action, log)
Then provide the log to the module at instantiation. 然后在实例化时将日志提供给模块。
I hope this helps. 我希望这有帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.