Python3添加日志记录级别 [英] Python3 add logging level

查看:169
本文介绍了Python3添加日志记录级别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这段代码对我来说很好.

import logging
import logging.handlers

logger = None


def create_logger():
    global logger
    logger = logging.getLogger('Logger')
    logger.setLevel(logging.DEBUG)
    handler = logging.handlers.RotatingFileHandler("C:/Users/user/Desktop/info.log", maxBytes=1000000, backupCount=20)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    handler.setFormatter(formatter)
    logger.addHandler(handler)


create_logger()
logger.info("Text info")
logger.debug("Text debug")
logger.warning("Text warning")
logger.error("Text error")
logger.critical("Text critical")

输出看起来很棒:

2017-12-19 15:06:43,021-记录器-信息-文本信息
2017-12-19 15:06:43,021-记录器-调试-文本调试
2017-12-19 15:06:43,022-记录器-警告-文本警告
2017-12-19 15:06:43,022-记录器-错误-文本错误
2017-12-19 15:06:43,022-记录器-严重-文本严重

好吧,我想添加一个新的日志记录级别,如下所示:

logger.message("Text message")  

输出应该是这样

2017-12-19 15:06:43,022-记录器-消息-短信

谢谢

解决方案

来自日志记录级别的概述:

但是,如果您仍然愿意,可以设置自己的日志级别:

logging模块中,_levelToName_nameToLevel是日志记录名称和级别之间的映射. addLevelName()函数可以代替您手动添加它们.

在此处,添加了名为 MESSAGE 的新日志记录级别,日志级别为 25 :

import logging

# Define MESSAGE log level
MESSAGE = 25

# "Register" new loggin level
logging.addLevelName(MESSAGE, 'MESSAGE')  # addLevelName(25, 'MESSAGE')

# Verify
assert logging.getLevelName(MESSAGE) == 'MESSAGE'

如果您不想创建自己的记录器类,但仍然希望记录其他日志级别,则可以在传统记录器上使用Logger.log(level, msg)方法:

logging.log(MESSAGE, 'This is a message')

直接添加消息

 def message(self, msg, *args, **kwargs):
    if self.isEnabledFor(MESSAGE):
        self._log(MESSAGE, msg, args, **kwargs) 

使logging功能在logging中可用:

 logging.message = message
 # or setattr(logging, 'message', message)

使记录器中的message()功能可用:

 logging.Logger.message = message
 # or setattr(logging.Logger, 'message', message)

制作自定义Logger类

您可以创建自己的logger类来创建message(msg)方法,与其他方法(例如info(msg)warning(msg)等)类似地使用

在下面的示例中,使用message(msg)方法创建了一个新的记录器,用于记录 MESSAGE :

class MyLogger(logging.Logger):
    def message(self, msg, *args, **kwargs):
        if self.isEnabledFor(MESSAGE):
            self._log(MESSAGE, msg, args, **kwargs)

获取记录器

我不确定使其与logging.getLogger(name)一起使用的最佳方法是什么,但是下面是两种方法. 参考评论,我认为第一种方法更好:

任一将新的记录器设置为默认的记录类,这意味着新的记录器实例将属于MyLogger类,而不是默认的logging.Logger类:

logging.setLoggerClass(MyLogger)
logger = logging.getLogger('A new logger name')
logger.message('This seems to work')
assert isInstance(logger, MyLogger)

只需创建一个记录器实例并将其添加到活动logging.Manager实例中的loggerDict中( EDIT :不推荐,请参见注释):

my_logger = MyLogger('Foo')
logging.Logger.manager.loggerDict['Foo'] = my_logger
logger = logging.getLogger('Foo')
logger.message('This is the same instance as my_logger')
assert logger is my_logger

使用新的日志级别

# Use the new logger class
logger.warning('Custom log levels might be a bad idea')
logger.message('Here is a message')
# Log with custom log level:
logger.log(MESSAGE, 'This is a message')

这假定MESSAGE被预定义为代表日志级别的整数. (例如前面提到的 25 )

I have this code which works just fine for me.

import logging
import logging.handlers

logger = None


def create_logger():
    global logger
    logger = logging.getLogger('Logger')
    logger.setLevel(logging.DEBUG)
    handler = logging.handlers.RotatingFileHandler("C:/Users/user/Desktop/info.log", maxBytes=1000000, backupCount=20)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    handler.setFormatter(formatter)
    logger.addHandler(handler)


create_logger()
logger.info("Text info")
logger.debug("Text debug")
logger.warning("Text warning")
logger.error("Text error")
logger.critical("Text critical")

And the output looks great:

2017-12-19 15:06:43,021 - Logger - INFO - Text info
2017-12-19 15:06:43,021 - Logger - DEBUG - Text debug
2017-12-19 15:06:43,022 - Logger - WARNING - Text warning
2017-12-19 15:06:43,022 - Logger - ERROR - Text error
2017-12-19 15:06:43,022 - Logger - CRITICAL - Text critical

Well, I want to add a new logging level like this:

logger.message("Text message")  

And the output should be like this

2017-12-19 15:06:43,022 - Logger - MESSAGE - Text message

Thanks

解决方案

From Logging documentation (emphasis added):

Defining your own levels is possible, but should not be necessary, as the existing levels have been chosen on the basis of practical experience. However, if you are convinced that you need custom levels, great care should be exercised when doing this, and it is possibly a very bad idea to define custom levels if you are developing a library. That’s because if multiple library authors all define their own custom levels, there is a chance that the logging output from such multiple libraries used together will be difficult for the using developer to control and/or interpret, because a given numeric value might mean different things for different libraries.

An overview of default logging levels:

But if you still want to, you can make your own log level:

In the logging-module, _levelToName and _nameToLevel are mappings between logging names and levels. Instead of manually adding to them, the addLevelName() function does this for you.

Here, a new logging level called MESSAGE is added with log level 25:

import logging

# Define MESSAGE log level
MESSAGE = 25

# "Register" new loggin level
logging.addLevelName(MESSAGE, 'MESSAGE')  # addLevelName(25, 'MESSAGE')

# Verify
assert logging.getLevelName(MESSAGE) == 'MESSAGE'

If you don't want to make your own logger class but still wants to log other log levels, then you can use the Logger.log(level, msg)-method on the traditional loggers:

logging.log(MESSAGE, 'This is a message')

EDIT: Add message directly

 def message(self, msg, *args, **kwargs):
    if self.isEnabledFor(MESSAGE):
        self._log(MESSAGE, msg, args, **kwargs) 

Make the message()-function available in logging:

 logging.message = message
 # or setattr(logging, 'message', message)

Make the message()-function available in the logger:

 logging.Logger.message = message
 # or setattr(logging.Logger, 'message', message)

Make custom Logger class

You could make your own logger class to make a message(msg)-method, to be used similarily as the others (e.g. info(msg), warning(msg), etc.)

In the following example, a new logger is made with a message(msg)-method to log MESSAGE:

class MyLogger(logging.Logger):
    def message(self, msg, *args, **kwargs):
        if self.isEnabledFor(MESSAGE):
            self._log(MESSAGE, msg, args, **kwargs)

Get logger

I'm not sure of what's the best way to make it work with logging.getLogger(name), but below are two approaches. Ref. comments, I believe the first approach is better:

Either make the new logger the default logging class, which means new logger instances will be of the MyLogger class instead of the default logging.Logger class:

logging.setLoggerClass(MyLogger)
logger = logging.getLogger('A new logger name')
logger.message('This seems to work')
assert isInstance(logger, MyLogger)

Or just make an instance of the logger and add it to the loggerDict in the active logging.Manager instance (EDIT: not recommended, see comments):

my_logger = MyLogger('Foo')
logging.Logger.manager.loggerDict['Foo'] = my_logger
logger = logging.getLogger('Foo')
logger.message('This is the same instance as my_logger')
assert logger is my_logger

Use the new log level

# Use the new logger class
logger.warning('Custom log levels might be a bad idea')
logger.message('Here is a message')
# Log with custom log level:
logger.log(MESSAGE, 'This is a message')

This assumes that MESSAGE is predefined as an integer numerical value representing the log level. (E.g. 25 as previously mentioned)

这篇关于Python3添加日志记录级别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆