扩展Python日志记录器

3
我希望您能够简单地扩展标准Python库中定义的logging功能。我只想选择是否将我的日志打印到屏幕上。例如:通常记录警告时,您会调用:
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s: %(message)s', filename='log.log', filemode='w')
logging.warning("WARNING!!!")

这将设置日志的配置并将警告放入日志中。
我希望能够类似于以下调用的内容:
logging.warning("WARNING!!!", True)

True表示日志也会被打印到标准输出。

我看过一些重写记录器类的实现示例,但我对这个语言还很陌生,不太明白正在发生什么,或者如何实现这个想法。任何帮助将不胜感激 :)


为什么你想在日志记录现场设置这些细节,而不是在一个地方进行配置呢?我不确定你的意思...也许你是在问为什么我会在每次记录日志之前调用basicConfig函数,答案是我不会这样做,那只是为了展示我如何配置我的日志。 - Colton Phillips
不,我的意思是:为什么你想要为每个日志记录语句声明它应该去stdout(除了其他东西或不去)? - user395760
没有人反对将一些日志消息发送到标准输出(stdout)。使用足够高的级别并添加代码(可能是一个处理程序,如Alison所描述的那样),将该级别的消息发送到stdout,但要在一个地方完成。如果您改变主意或想要添加额外的功能(例如,为什么不将其打印到stderr? 或者也许stdout更好?等等),那么只需要调整一个地方即可。 - user395760
因为有些日志记录并不是对用户来说很关键的信息,用户可以查看日志以获取更多信息,而有些则是至关重要的,应该向用户显示。我想,如果以某种方式设置,使得 logging.warning() 和 logging.error() 显示给用户,而 logging.debug() 和 logging.info() 则不显示,那么就可以满足要求了... - Colton Phillips
这就是日志记录应该完成的方式 ;) 过滤特定级别的日志是一项基本任务。在代码中,使用适当的级别记录日志,并配置记录器以按照您希望的方式显示所需的内容。我只能再次强调,您应该阅读[日志记录教程](http://docs.python.org/howto/logging.html)。 - user395760
显示剩余4条评论
3个回答

8
Python日志模块定义了以下几个类:
Loggers:发出日志消息的对象。
Handlers:将这些消息发送到目标位置的对象。
Formatters:格式化日志消息的对象。
Filters:过滤日志消息的对象。
一个Logger可以拥有Handlers,你可以通过调用addHandler()方法来添加它们。一个Handler可以拥有FiltersFormatters,你可以通过分别调用addFilter()setFormatter()方法来添加它们。
其工作原理如下:
import logging

# make a logger
main_logger = logging.getLogger("my logger")
main_logger.setLevel(logging.INFO)

# make some handlers
console_handler = logging.StreamHandler() # by default, sys.stderr
file_handler    = logging.FileHandler("my_log_file.txt")

# set logging levels
console_handler.setLevel(logging.WARNING)
file_handler.setLevel(logging.INFO)

# add handlers to logger
main_logger.addHandler(console_handler)
main_logger.addHandler(file_handler)

现在,您可以像这样使用此对象:
main_logger.info("logged in the FILE")
main_logger.warning("logged in the FILE and on the CONSOLE")

如果您只是在计算机上运行python,您可以在交互式控制台中输入上述代码,您应该能够看到输出。 日志文件将在当前目录中创建,如果您有权限在其中创建文件。

希望这能帮助到您!


2

可以通过覆盖 logging.getLoggerClass() 方法来向日志记录器添加新功能。我编写了一个简单的类,在 stdout 中打印绿色消息。

代码中最重要的部分:

class ColorLogger(logging.getLoggerClass()):
    __GREEN = '\033[0;32m%s\033[0m'
    __FORMAT = {
        'fmt': '%(asctime)s %(levelname)s: %(message)s',
        'datefmt': '%Y-%m-%d %H:%M:%S',
    }

    def __init__(self, format=__FORMAT):
        formatter = logging.Formatter(**format)

        self.root.setLevel(logging.INFO)
        self.root.handlers = []

        (...)

        handler = logging.StreamHandler()
        handler.setFormatter(formatter)
        self.root.addHandler(handler)

    def info(self, message):
        self.root.info(message)

    (...)

    def info_green(self, message):
        self.root.info(self.__GREEN, message)

(...)

if __name__ == '__main__':
    logger = ColorLogger()
    logger.info("This message has default color.")
    logger.info_green("This message is green.")

最好不要覆盖root日志记录器。 - hjpotter92
1
这是如何覆盖“root”记录器的?它是通过子类化logging.getLoggerClass()并在根记录器上设置一些属性以及调用其某些方法来实现的。 - Bernd Wechner

1
处理程序将日志记录(由记录器创建)发送到适当的目标位置。
(来自文档:http://docs.python.org/library/logging.html
只需使用日志对象设置多个处理程序,一个用于写入文件,另一个用于写入屏幕。
更新:
以下是一个示例函数,您可以在类中调用它以设置带有处理程序的日志记录。
def set_up_logger(self):
    # create logger object
    self.log = logging.getLogger("command")
    self.log.setLevel(logging.DEBUG)

    # create console handler and set min level recorded to debug messages
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)

    # add the handler to the log object        
    self.log.addHandler(ch)

您只需要为文件设置另一个处理程序,就像已经存在的StreamHandler代码一样,并将其添加到日志对象中。代码中的ch.setLevel(logging.DEBUG)表示此特定处理程序将接收DEBUG或更高级别的日志消息。您可能希望将自己的设置为WARNING或更高级别,因为您只想将更重要的内容发送到控制台。因此,您的日志记录将按以下方式工作:

self.log.info("Hello, World!") -> goes to file
self.log.error("OMG!!") -> goes to file AND console

你能澄清一下你的意思吗?我正在查看文档,发现日志类有一个addHandler()函数,这很直观,但实际上如何设置处理程序我不知道怎么做。我开始觉得在所有我认为应该打印给用户的日志下面添加一个print()语句可能会更容易... - Colton Phillips
1
@Colton:你可能想阅读日志记录教程,特别是关于处理程序的部分和有用处理程序列表。链接如下:http://docs.python.org/howto/logging.html#handlers 和 http://docs.python.org/howto/logging.html#useful-handlers。 - user395760

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接