如何在 Python 中使用多记录器
How to use multi logger in Python
我尝试使用两个不同的记录器来处理不同的日志级别。例如,我希望将信息消息存储在文件中并且不记录错误消息。一些特殊功能的错误信息将通过电子邮件发送给用户。
我写了一个简单的程序来测试日志模块。
代码:
import logging
def_logger = logging.getLogger("debuglogger")
def_logger.setLevel(logging.DEBUG)
maillogger = logging.getLogger("mail")
maillogger.setLevel(logging.ERROR)
mailhandler = logging.StreamHandler()
mailhandler.setLevel(logging.ERROR)
mailhandler.setFormatter(logging.Formatter('Error: %(asctime)s - %(name)s - %(levelname)s - %(message)s'))
maillogger.addHandler(mailhandler)
print(def_logger.getEffectiveLevel())
print(maillogger.getEffectiveLevel())
def_logger.info("info 1")
maillogger.info("info 2")
def_logger.error("error 1")
maillogger.error("error 2")
输出:
Output result
我可以看到他们的水平是正确的,但他们两个表现得好像水平是错误的。
如何正确配置它们?
答:根据蓝调的建议,我添加了一个处理程序,它解决了我的问题。
这是修改后的代码:
import logging
def_logger = logging.getLogger("debuglogger")
def_logger.setLevel(logging.DEBUG)
def_logger.addHandler(logging.StreamHandler()) #added a handler here
maillogger = logging.getLogger("mail")
maillogger.setLevel(logging.ERROR)
mailhandler = logging.StreamHandler()
mailhandler.setLevel(logging.ERROR)
mailhandler.setFormatter(logging.Formatter('Error: %(asctime)s - %(name)s - %(levelname)s - %(message)s'))
maillogger.addHandler(mailhandler)
print(def_logger.getEffectiveLevel())
print(maillogger.getEffectiveLevel())
def_logger.info("info 1")
maillogger.info("info 2")
def_logger.error("error 1")
maillogger.error("error 2")
def_logger 及其父项都没有附加处理程序。所以发生的事情是日志记录模块回退到 logging.lastResort
,默认情况下它是一个具有警告级别的 StreamHandler。这就是信息消息没有出现而错误出现的原因。因此,要解决您的问题,请将处理程序附加到 def_logger.
注意:在您的场景中,两个记录器的唯一父级是默认根处理程序。
您可以为每个记录器或处理程序添加一个 filter
以仅处理感兴趣的记录
import logging
def filter_info(record):
return True if record.levelno == logging.INFO else False
def filter_error(record):
return True if record.levelno >= logging.ERROR else False
# define debug logger
def_logger = logging.getLogger("debuglogger")
def_logger.setLevel(logging.DEBUG)
def_logger.addFilter(filter_info) # add filter directly to this logger since you didn't define any handler
# define handler for mail logger
mail_handler = logging.StreamHandler()
mail_handler.setLevel(logging.ERROR)
mail_handler.setFormatter(logging.Formatter('Error: %(asctime)s - %(name)s - %(levelname)s - %(message)s'))
mail_handler.addFilter(filter_error) # add filter to handler
mail_logger = logging.getLogger("mail")
mail_logger.setLevel(logging.ERROR)
mail_logger.addHandler(mail_handler)
# test
def_logger.info("info 1")
mail_logger.info("info 2")
def_logger.error("error 1")
mail_logger.error("error 2")
如果filter
return True
,处理日志记录。否则跳过。
注:
附加到 logger
的过滤器不会被后代记录器生成的日志记录调用。例如,如果您向记录器 A
添加过滤器,则不会为记录器 A.B
或 A.B.C
.
生成的记录调用它
附加到 handler
的过滤器在该处理程序发出事件之前被查询。
这意味着您只需要一个 logger
并添加两个带有不同过滤器的 handler
。
import logging
def filter_info(record):
return True if record.levelno == logging.INFO else False
def filter_error(record):
return True if record.levelno >= logging.ERROR else False
# define your logger
logger = logging.getLogger("myapp")
logger.setLevel(logging.DEBUG)
# define handler for file
file_handler = logging.FileHandler('path_to_log.txt')
file_handler.level = logging.INFO
file_handler.addFilter(filter_info) # add filter to handler
# define handler for mail
mail_handler = logging.StreamHandler()
mail_handler.setLevel(logging.ERROR)
mail_handler.setFormatter(logging.Formatter('Error: %(asctime)s - %(name)s - %(levelname)s - %(message)s'))
mail_handler.addFilter(filter_error) # add filter to handler
logger.addHandler(file_handler)
logger.addHandler(mail_handler)
# test
logger.info("info 1")
logger.info("info 2")
logger.error("error 1")
logger.error("error 2")
我尝试使用两个不同的记录器来处理不同的日志级别。例如,我希望将信息消息存储在文件中并且不记录错误消息。一些特殊功能的错误信息将通过电子邮件发送给用户。
我写了一个简单的程序来测试日志模块。
代码:
import logging
def_logger = logging.getLogger("debuglogger")
def_logger.setLevel(logging.DEBUG)
maillogger = logging.getLogger("mail")
maillogger.setLevel(logging.ERROR)
mailhandler = logging.StreamHandler()
mailhandler.setLevel(logging.ERROR)
mailhandler.setFormatter(logging.Formatter('Error: %(asctime)s - %(name)s - %(levelname)s - %(message)s'))
maillogger.addHandler(mailhandler)
print(def_logger.getEffectiveLevel())
print(maillogger.getEffectiveLevel())
def_logger.info("info 1")
maillogger.info("info 2")
def_logger.error("error 1")
maillogger.error("error 2")
输出: Output result
我可以看到他们的水平是正确的,但他们两个表现得好像水平是错误的。
如何正确配置它们?
答:根据蓝调的建议,我添加了一个处理程序,它解决了我的问题。 这是修改后的代码:
import logging
def_logger = logging.getLogger("debuglogger")
def_logger.setLevel(logging.DEBUG)
def_logger.addHandler(logging.StreamHandler()) #added a handler here
maillogger = logging.getLogger("mail")
maillogger.setLevel(logging.ERROR)
mailhandler = logging.StreamHandler()
mailhandler.setLevel(logging.ERROR)
mailhandler.setFormatter(logging.Formatter('Error: %(asctime)s - %(name)s - %(levelname)s - %(message)s'))
maillogger.addHandler(mailhandler)
print(def_logger.getEffectiveLevel())
print(maillogger.getEffectiveLevel())
def_logger.info("info 1")
maillogger.info("info 2")
def_logger.error("error 1")
maillogger.error("error 2")
def_logger 及其父项都没有附加处理程序。所以发生的事情是日志记录模块回退到 logging.lastResort
,默认情况下它是一个具有警告级别的 StreamHandler。这就是信息消息没有出现而错误出现的原因。因此,要解决您的问题,请将处理程序附加到 def_logger.
注意:在您的场景中,两个记录器的唯一父级是默认根处理程序。
您可以为每个记录器或处理程序添加一个 filter
以仅处理感兴趣的记录
import logging
def filter_info(record):
return True if record.levelno == logging.INFO else False
def filter_error(record):
return True if record.levelno >= logging.ERROR else False
# define debug logger
def_logger = logging.getLogger("debuglogger")
def_logger.setLevel(logging.DEBUG)
def_logger.addFilter(filter_info) # add filter directly to this logger since you didn't define any handler
# define handler for mail logger
mail_handler = logging.StreamHandler()
mail_handler.setLevel(logging.ERROR)
mail_handler.setFormatter(logging.Formatter('Error: %(asctime)s - %(name)s - %(levelname)s - %(message)s'))
mail_handler.addFilter(filter_error) # add filter to handler
mail_logger = logging.getLogger("mail")
mail_logger.setLevel(logging.ERROR)
mail_logger.addHandler(mail_handler)
# test
def_logger.info("info 1")
mail_logger.info("info 2")
def_logger.error("error 1")
mail_logger.error("error 2")
如果filter
return True
,处理日志记录。否则跳过。
注:
附加到
生成的记录调用它logger
的过滤器不会被后代记录器生成的日志记录调用。例如,如果您向记录器A
添加过滤器,则不会为记录器A.B
或A.B.C
.附加到
handler
的过滤器在该处理程序发出事件之前被查询。
这意味着您只需要一个 logger
并添加两个带有不同过滤器的 handler
。
import logging
def filter_info(record):
return True if record.levelno == logging.INFO else False
def filter_error(record):
return True if record.levelno >= logging.ERROR else False
# define your logger
logger = logging.getLogger("myapp")
logger.setLevel(logging.DEBUG)
# define handler for file
file_handler = logging.FileHandler('path_to_log.txt')
file_handler.level = logging.INFO
file_handler.addFilter(filter_info) # add filter to handler
# define handler for mail
mail_handler = logging.StreamHandler()
mail_handler.setLevel(logging.ERROR)
mail_handler.setFormatter(logging.Formatter('Error: %(asctime)s - %(name)s - %(levelname)s - %(message)s'))
mail_handler.addFilter(filter_error) # add filter to handler
logger.addHandler(file_handler)
logger.addHandler(mail_handler)
# test
logger.info("info 1")
logger.info("info 2")
logger.error("error 1")
logger.error("error 2")