一文详解python日志loggin的使用

一文详解python日志loggin的使用

一个通用的日志系统对于系统软件开发来说非常重要,对于Python而言,我们通常使用python 自带的 logging 来进行日志的管理。对于一些小型的项目来说logging是完全够用的,且非常简单易上手。

1. 一个简单的例子认识logging 基本用法

话不多说,咱们直接上实例,从例子中往往是最容易去理解某个工具的用法:
logging日志的实现主要通过一下5个步骤来实现的。

import logging
#1. 创建logger实例
logger = logging.getLogger('logtop')
#2. 设置logger实例的等级
logger.setLevel(logging.INFO)
#3. 创建formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(message)s')
#4. 创建控制台handler
cons_handler = logging.StreamHandler()
cons_handler.setLevel(logging.INFO) 
cons_handler.setFormatter(formatter)
#5. 添加handler到logger
logger.addHandler(cons_handler)

#运行
#这里用logger实例输出日志
logger.critical('this is an critical')  
logger.error('错误日志')  
logger.warning('this is a warning')  
logger.info('这是 info 日志')    
logger.debug('debug 信息 了')   

运行输出结果如下所示:

2022-08-25 14:14:58,989 - logtop - 24 - CRITICAL - this is an critical
2022-08-25 14:14:58,990 - logtop - 25 - ERROR - 错误日志
2022-08-25 14:14:59,003 - logtop - 26 - WARNING - this is a warning
2022-08-25 14:14:59,004 - logtop - 27 - INFO - 这是 info 日志

2. 用法详解

2.1 创建logger实例
#1. 创建logger实例
logger = logging.getLogger('logtop')

此处我们创建了一个实例logger, 名为’logtop’

2.2 设置logger实例的日志报告等级
#2. 设置logger实例的等级
logger.setLevel(logging.INFO)

日志包含以下五个级别:

级别何时使用等效数值
DEBUG细节信息,仅当诊断问题时适用。10
INFO确认程序按预期运行。20
WARNING表明有已经或即将发生的意外(例如:磁盘空间不足)。程序仍按预期进行。30
ERROR由于严重的问题,程序的某些功能已经不能正常执行40
CRITICAL严重的错误,表明程序已不能继续执行50

报告优先级是依次增加的,而loggin只会记录级别比设定日志等级大或相等级别的日志。即,例如上面例子中,我们设定的日志等级为INFO,那结果只会输出INFO到CRITICAL级别的日志, 而不会输出下面的DEBUG级别的日志。

2.3 创建日志格式
#设定日志格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(message)s')
#示例: 2022-08-24 16:29:05,504 - logtop - 24 - CRITICAL

日志可以包含多方面的内容:

Attribute nameFormatDescription
argsYou shouldn’t need to format this yourself.The tuple of arguments merged into msg to produce message, or a dict whose values are used for the merge (when there is only one argument, and it is a dictionary).
asctime%(asctime)sHuman-readable time when the LogRecord was created. By default this is of the form ‘2003-07-08 16:49:45,896’ (the numbers after the comma are millisecond portion of the time).
created%(created)fTime when the LogRecord was created (as returned by time.time()).
exc_infoYou shouldn’t need to format this yourself.Exception tuple (à la sys.exc_info) or, if no exception has occurred, None.
filename%(filename)sFilename portion of pathname.
funcName%(funcName)sName of function containing the logging call.
levelname%(levelname)sText logging level for the message (‘DEBUG’, ‘INFO’, ‘WARNING’, ‘ERROR’, ‘CRITICAL’).
levelno%(levelno)sNumeric logging level for the message (DEBUG, INFO, WARNING, ERROR, CRITICAL).
lineno%(lineno)dSource line number where the logging call was issued (if available).
message%(message)sThe logged message, computed as msg % args. This is set when Formatter.format() is invoked.
module%(module)sModule (name portion of filename).
msecs%(msecs)dMillisecond portion of the time when the LogRecord was created.
msgYou shouldn’t need to format this yourself.The format string passed in the original logging call. Merged with args to produce message, or an arbitrary object (see Using arbitrary objects as messages).
name%(name)sName of the logger used to log the call.
pathname%(pathname)sFull pathname of the source file where the logging call was issued (if available).
process%(process)dProcess ID (if available).
processName%(processName)sProcess name (if available).
relativeCreated%(relativeCreated)dTime in milliseconds when the LogRecord was created, relative to the time the logging module was loaded.
stack_infoYou shouldn’t need to format this yourself.Stack frame information (where available) from the bottom of the stack in the current thread, up to and including the stack frame of the logging call which resulted in the creation of this record.
thread%(thread)dThread ID (if available).
threadName%(threadName)sThread name (if available).

logging.Formatter(fmt=None, datefmt=None, style=‘%’, defaults=None) 接受多个参数:

paraDescription示例
fmt消息的格式化字符串fmt=‘%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(message)s’
datefmt日期字符串,默认为ISO8601日期格式datefmt=‘%Y-%m-%d %H:%M:%S’
style可以是 ‘%’、‘{’ 或 ‘$’ 之一,并确定格式字符串如何与其数据合并style=‘%’
defaults具有用于自定义字段的默认值的字典。例如: logging.Formatter(‘%(ip)s %(message)s’, defaults={“ip”: None})defaults={“ip”: None}
2.4 创建handler
#4. 创建控制台handler
cons_handler = logging.StreamHandler()
cons_handler.setLevel(logging.INFO) 
cons_handler.setFormatter(formatter)
#4. 创建文件handler
file_handler = logging.FileHandler('log.txt')
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(formatter)

Handler 处理器类型常用的有三个,StreamHandler,FileHandler,NullHandler。
StreamHandler:日志以数据流形式输出,即输出到stdout
FileHandler:日志输出到文件里头
NullHandler:啥也不做

创建Handler之后,可以通过使用以下方法设置日志级别,设置格式化器Formatter,增加或删除过滤器Filter。

Handler.setLevel(logging.WARN) # 指定日志级别,低于该级别的日志将被忽略。注意这个级别和上面设定的日志级别的区别: 上面logger.setLevel() 设定的级别限制同样作用于Handler级别。即logger.setLevel() 设定了INFO级别,那即使Handler设定为DEBUG,日志也只会到INFO级别。

Handler.setFormatter(formatter ) # 设置一个格式化器formatter,此处我们可以用上面设定的formatter

2.5 添加handler到logger实例
#5. 添加handler到logger
logger.addHandler(cons_handler)

使用 addHandler() 即可添加handler到logger实例

3. 日志通用代码(万能)

话不多说:

import logging
import sys

class Logger(object):
    def __init__(self):
        logger = logging.getLogger(__name__)
        logger.setLevel(logging.DEBUG)
        logger.handlers.clear() # 每次记录了日志内容之后,就把之前的filehandler移除,防止重复打印

        logFile = 'validated.log'
        handler = logging.StreamHandler()
        #handler = logging.FileHandler('log.txt', mode='w') # 若打印到文件使用此handle
        handler.setLevel(logging.DEBUG)
        format = logging.Formatter('%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(message)s')     
        handler.setFormatter(format)
        logger.addHandler(handler)
        self.logger = logger
    def debug(self, msg):
        self.logger.debug(msg)
    def info(self, msg):
        self.logger.info(msg)
    def warning(self, msg):
        self.logger.warning(msg)
    def error(self, msg):
        self.logger.error(msg)
        #sys.exit(1) #可以设定退出及其退出码
    def critical(self, msg):
        self.logger.critical(msg)
        #sys.exit(1) 

这样我们在其他地方就可以直接调用上面定好的类来实现日志输出了。
类日志的信息可以根据实际情况自定义:

Logger().debug('this is an debug')
Logger().info('this is an info')
Logger().warning('this is an warning')
Logger().error('this is an error')
Logger().critical('this is an critical')
2022-08-25 11:35:20,719 - __main__ - 20 - DEBUG - this is an debug
2022-08-25 11:35:20,721 - __main__ - 22 - INFO - this is an info
2022-08-25 11:35:20,725 - __main__ - 24 - WARNING - this is an warning
2022-08-25 11:35:20,727 - __main__ - 26 - ERROR - this is an error
2022-08-25 11:35:20,728 - __main__ - 29 - CRITICAL - this is an critical

欧了 !!! 赶紧加入你的收藏夹吃灰去吧~

参考资料
http://www.juzicode.com/python-tutorial-logging/
https://docs.python.org/zh-cn/3/howto/logging.html
https://docs.python.org/3/library/logging.html

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值