两个写使用python日志记录

时间:2014-12-24 17:15:52

标签: python class 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

我在"被称为类(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))

当我单独调用它时,每self.logger次调用获得一个输出;但是当我从tdoa类中调用它时,它写了TWICE: 例如:

 Name: actualLat         Value:36.455444
 Name: actualLat         Value:36.455444

如何解决这个问题?

2 个答案:

答案 0 :(得分:0)

每次使用以下行构造类实例时,都会向父类添加处理程序:

self.logger.addHandler(console)

所以,如果你做了类似的事情:

for _ in range(x):
    SubClass1()
some_operation_with_logging()

您应该看到x条消息,因为您只是通过对父母x进行x次调用,将__init__处理程序添加到记录器中。

您不希望这样做,请确保只添加一个处理程序 ! 您可以使用以下代码访问记录器的处理程序列表:logger.handlers


此外,如果您在两个类(名为"TDOA")中使用相同的记录器,请在两者中使用此行:

self.logger=logging.getLogger('TDOA')

确保您同步记录器实例化,或使用单独的记录器。


我使用的是什么:

除了为每个实例设置一个私有记录器之外,您可能还需要一个适用于所有实例的记录器,或者更准确地说 - 对于类本身:

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

现在您知道logger每个类实例化一次(而不是每个实例一次),并且某个类的所有实例都使用相同的记录器。

答案 1 :(得分:0)

我发现一些链接表明子模块应该在 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())

注意:如果用户决定不提供记录器,则添加nullhandler以避免警告。

然后,如果你想调试你的子模块:

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)

然后在实例化时将日志提供给模块。

我希望这会有所帮助。