如何在我的程序中更好地使用日志记录模块?

时间:2011-11-28 05:59:49

标签: python logging file-io

当我开始使用我的脚本时,我没有考虑记录模块,因此我只是简单地编写代码:

LogMethod(LogFileName, LogMessage):
    LogRlock.acquire()

    LogFile = open(LogFileName, "a")
    LogFile.write(LogMessage)
    LogFile.close()

    LogRlock.release()

但是现在由于日志模块可以在日志文件大小/格式控制等方面做得更好,我即将重写上面的方法。好吧,我想要对这个方法进行简单的修改,假设我会这样编码:

LogMethod(LogFileName, LogMessage):
    #### Do I need to destroy the instance Logger at the end of this method?
    LogRlock.acquire()

    Logger = logging.getLogger("Demo")
    Logger.setLevel(logging.DEBUG)
    SizeHandler = logging.handlers.RotatingFileHandler(filename = LogFileName, mode = "a", maxBytes = 1000000)
    SimpleFormatter = logging.Formatter(fmt = '%(asctime)s%(message)s', datefmt = '[%Y-%m-%d, %H:%M:%S]:')
    SizeHandler.setFormatter(SimpleFormatter)
    Logger.addHandler(SizeHandler)
    Logger.info(LogMessage)

    LogRlock.release()

Python文档说日志模块是线程安全的,所以我想我真的不需要LogRlock,对吧?还有一个问题,我需要在上面的方法结束时销毁实例吗?如果是这样,我该怎么做?这是一种使用日志记录模块的安全方法吗?

非常感谢

2 个答案:

答案 0 :(得分:2)

使用记录器并定义其属性是两个不同的任务,应将它们分开,以便将业务逻辑与配置逻辑分开。

通常,在应用程序中,您可以通过名称来定位记录器。基本上,你需要记录的所有方法都是这样的方法:

def logMethod(loggerName, logMessage):
    logger = logging.getLogger(loggerName)
    logger.info(logMessage)

定义记录器属性可以单独完成,如下所示:

def configureLogger(loggerName):
    logger = logging.getLogger(loggerName)
    logger.setLevel(logging.DEBUG)
    sizeHandler = logging.handlers.RotatingFileHandler(filename = LogFileName, mode = "a", maxBytes = 1000000)
    simpleFormatter = logging.Formatter(fmt = '%(asctime)s%(message)s', datefmt = '[%Y-%m-%d, %H:%M:%S]:')
    sizeHandler.setFormatter(simpleFormattesr)
    logger.addHandler(sizeHandler)

上面提到的“手动”日志记录配置的另一种替代方法是使用logging configuration file或使用configuration dictionary

Python开发人员不必关心销毁对象,这是由Python的垃圾收集器完成的。对于logging.Logger类,这甚至是显式销毁记录器的错误:记录器实例由记录模块存储,以便在每次调用logging.getLogger时返回相同的实例(如果记录器名称相同) ()提供)(方法logging.getLogger(“Demo”)在第一次调用时创建一个新实例) 在你的情况下,这意味着每次调用logMethod时,RotatingFileHandler都会在你的记录器中添加第二个,第三个,第四个... ...

PS:Python编码约定:函数和变量以小写字母开头

答案 1 :(得分:1)

  

Python文档说日志记录模块是线程安全的,所以我想我真的不需要LogRlock,对吗?

正确,您不需要锁定来保护您的日志记录代码。

  

还有一个问题,我需要在上面的方法结束时销毁实例吗?如果是这样,我该怎么做?

不,你没有。实际上,您无法在Python中销毁对象。当没有引用它们时,它们将自动被垃圾收集。

除此之外,Logger对象旨在持续程序的生命周期。即使你可以在记录功能结束时销毁它,你也不应该。

  

这是一种使用日志记录模块的安全方法吗?

不,不是真的。正如评论中指出的那样,您在日志记录方法中执行设置操作(如添加处理程序和格式化程序),而在程序开始时应该只执行一次。你现在这样做的方式,每次你记录一条消息,你最终都会添加一个处理程序,每个处理程序打印出它收到的每条消息,所以你会发现你记录的第一条消息被打印出来一次,第二条消息一个打印出来两次,第三个打印三次,等等,直到你用你不需要的日志消息副本充斥你的日志文件。

我建议使用某种设置函数,在程序开始时调用一次以配置日志记录行为。有关设置记录器级别,添加处理程序和添加格式化程序的所有内容都在那里。然后,在您使用日志记录代码的每个模块(.py文件)中,在模块级别,您可以获得适当的记录器并将其存储在模块级变量中:

logger = logging.getLogger("package.module")

或者,如果您在模块中使用多个记录器,请为每个记录器执行此操作。在您需要记录消息的每个功能中,您只需执行

def foo():
    ...
    logger.info("message")
    ...

logger.info来电取代了您自己的LogMethod