`

这是看过对python日志解释比较全的文章

阅读更多

 

软件开发中通过日志记录程序的运行情况是一个开发的好习惯,对于错误排查和系统运维都有很大帮助。Python标准库自带日志模块,已经足够强大,大部分情况下,python程序的日志功能直接调用标准库的日志模块即可。《The Hitchhiker’s Guide to Python》已对“日志”进行了详细阐述,python的官方文档也对日志做了说明,但Gevin依然感觉,通过这些英文资料,还不能让初学者在短时间迅速掌握python日志模块的使用,因此按照自己的思路,把相关内容做了如下整理,并附加一些Gevin认为文档中没有说明清楚的内容。

1. 基本用法

如果开发轻量级的应用,对日志的需求也比较简单,直接参考如下示例,在相关代码逻辑中加入日志功能即可:

#!/usr/local/bin/python
# -*- coding: utf-8 -*-

import logging

logging.debug('debug message')
logging.info('info message')
logging.warn('warn message')
logging.error('error message')
logging.critical('critical message')

output:

WARNING:root:warn message
ERROR:root:error message
CRITICAL:root:critical message

默认情况下,logging模块将日志打印到屏幕上,日志级别为WARNING(即只有日志级别等于或高于WARNING的日志信息才会输出),日志格式为 warning level:instance name:warning message

1.1 将日志记录到文件中

将日志记录到文件中,只需在调用logging模块记录日志前,做个简单的配置即可:

#!/usr/local/bin/python
# -*- coding: utf-8 -*-

import logging

# 配置日志文件和日志级别
logging.basicConfig(filename='logger.log', level=logging.INFO)

logging.debug('debug message')
logging.info('info message')
logging.warn('warn message')
logging.error('error message')
logging.critical('critical message')

本样例在记录日志前,通过logging.basicConfig做简单配置,将日志记录到日志文件logger.log中,也修改了默认的日志等级,高于或等于INFO级别的日志信息,都会记录到日志文件中。

2. 更加完善的日志功能

2.1 几个关键概念

如果要更加灵活的使用日志模块,首先要了解日志模块是怎样工作的。 LoggerHandlerFormatterFilter是日志模块的几个基本概念,日志模块的工作原理要从这四个基本概念说起。

  • Logger 即记录器,Logger提供了日志相关功能的调用接口。
  • Handler 即处理器,将(记录器产生的)日志记录发送至合适的目的地。
  • Filter 即过滤器,提供了更好的粒度控制,它可以决定输出哪些日志记录。
  • Formatter 即格式化器,指明了最终输出中日志记录的格式。

2.1.1 Logger

Logger 即“记录器”,Logger对象实例是日志记录功能的载体,如:

#!/usr/local/bin/python
# -*- coding: utf-8 -*-

import logging

logger = logging.getLogger('simple_example')

logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')

值得一提的是,Logger对象从不直接实例化,而是通过模块级的功能logging.getLogger(name)创建Logger实例。调用 logging.getLogger(name) 功能时,如果传入的name参数值相同,则总是返回同一个Logger对象实例的引用。

如果没有显式的进行创建,则默认创建一个root logger,并应用默认的日志级别(WARN)、默认的处理器Handler(StreamHandler,即将日志信息打印输出在标准输出上),和默认的格式化器Formatter(默认的格式即为第一个简单使用程序中输出的格式)。

Logger类包含的成员和方法可以查看官方文档

2.1.2 Handler

Handler 将日志信息发送到设置的位置,可以通过Logger对象的addHandler()方法为Logger对象添加0个或多个handler。一种日志的典型应用场景为,系统希望将所有的日志信息保存到log文件中,其中日志等级等于或高于ERROR的消息还要在屏幕标准输出上显示,日志等级为CRITICAL的还需要发送邮件通知;这种场景就需要3个独立的handler来实现需求,这三个handler分别与指定的日志等级或日志位置做响应

需要一提的是,为Logger配置的handler不能是Handler基类对象,而是Handler的子类对象,常用的Handler为StreamHandlerFileHandler, 和NullHandler,Handler的全部子类及详细介绍可以查看官方文档相应页面如果需要了解更多关于Handler的信息,直接查看官方文档即可。

2.1.3 Formatter

Formatter 用于设置日志输出的格式,与前两个基本概念不同的是,该类可以直接初始化对象,即 formatter=logging.Formatter(fmt=None, datefmt=None),创建formatter时,传入分别fmtdatefmt参数来修改日志格式和时间格式,默认的日志格式为%(asctime)s - %(levelname)s - %(message)s,默认的时间格式为%Y-%m-%d %H:%M:%S

2.1.4 Filter

Filter 可用于Logger对象或Handler对象,用于提供比日志等级更加复杂的日志过滤方式。默认的filter只允许在指定logger层级下的日志消息通过过滤。例如,如果把filter设置为filter=logging.Filter('A.B'),则logger ‘A.B’, ‘A.B.C’, ‘A.B.C.D’, ‘A.B.D’ 产生的日志信息可以通过过滤,但'A.BB', 'B.A.B'均不行。如果以空字符串初始化filter,则所有的日志消息都可以通过过滤。

Filter在日志功能配置中是非必须的,只在对日志消息过滤需求比较复杂时配置使用即可。

2.2 日志产生流程

日志产生的流程逻辑参考下图即可:

 

 

2.3 日志模块的使用

日志模块使用的关键是“日志的配置”,日志配置好后,只要调用logger.INFO()logger.ERROR()等方法即可创建日志内容。

开发者可以通过三种方法配置日志模块:

  1. 在Python代码中显示创建loggers, handlers, formatters甚至filters,并调用这几个对象中的各个配置函数来完成日志配置
  2. 将配置信息写到配置文件中,然后读取配置文件信息来完成日志配置
  3. 将配置信息写到一个Dict中,然后读取这个配置字典来完成日志配置

2.3.1 通过代码配置并使用日志模块

通过代码配置日志模块简单方便,但如果需要修改配置时,需要改代码,因此不建议在大型项目中使用这种方法。

通过代码配置日志模块可以很好的理解日志模块的工作原理,用于学习,是一个很好的案例,因此Gevin也在下文中对此详细介绍。

1. 创建Logger

import logging

# create logger
logger = logging.getLogger('simple_example')

# Set default log level
logger.setLevel(logging.DEBUG)

2. 创建Handler


# create console handler and set level to warn

ch = logging.StreamHandler()
ch.setLevel(logging.WARN)

3. 创建Fomatter

# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

4. 配置Logger

# add formatter to ch
ch.setFormatter(formatter)

# add ch to logger
# The final log level is the higher one between the default and the one in handler
logger.addHandler(ch)

5. 使用日志模块

logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')

6. 完整的例子


#!/usr/local/bin/python
# -*- coding: utf-8 -*-

import logging

# create logger
logger = logging.getLogger('simple_example')

# Set default log level
logger.setLevel(logging.DEBUG)


ch = logging.StreamHandler()
ch.setLevel(logging.WARN)

ch2 = logging.FileHandler('logging.log')
ch2.setLevel(logging.INFO)

# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# add formatter to ch
ch.setFormatter(formatter)
ch2.setFormatter(formatter)

# add ch to logger
# The final log level is the higher one between the default and the one in handler
logger.addHandler(ch)
logger.addHandler(ch2)

# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')

2.3.2 通过配置文件配置并使用日志模块

通过配置文件配置日志模块时,配置文件通常使用.ini格式,日志模块需要调用fileConfig,即logging.config.fileConfig('logging_config.ini'),然后logger的使用方法与上面相同:


#!/usr/local/bin/python
# -*- coding: utf-8 -*-

import logging
import logging.config

logging.config.fileConfig('logging_config.ini')

# create logger
logger = logging.getLogger('root')

# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')

其中,logging_config.ini文件内容如下:

[loggers]
keys=root,simpleExample

[handlers]
keys=consoleHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler

[logger_simpleExample]
level=INFO
handlers=consoleHandler
qualname=simpleExample
propagate=0

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)

[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s

通过配置文件配置日志模块,逻辑与代码中配置一样,也是把loggerhandlerformatter定义好,然后组装到一起即可,无非ini配置和代码配置时的语法不通而已,开发者在基于ini文件配置日志模块时,只要参考上面例子做相应修改即可。

2.3.3 通过Dict对象配置并使用日志模块

基于Dict对象配置日志模块在python中应用广泛,很多Django或Flask项目都采用这种方式,但很多官方文档对这种方法介绍并不多,因此,本文提供一个使用样例,以后开发中参考该样例修改一下即可。


#!/usr/local/bin/python
# -*- coding: utf-8 -*-

import logging
import logging.config

config = {
    'version': 1,
    'formatters': {
        'simple': {
            'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
        },
    },
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
            'level': 'DEBUG',
            'formatter': 'simple'
        },
        'file': {
            'class': 'logging.FileHandler',
            'filename': 'logging.log',
            'level': 'DEBUG',
            'formatter': 'simple'
        },
    },
    'loggers':{
        'root': {
            'handlers': ['console'],
            'level': 'DEBUG',
            # 'propagate': True,
        },
        'simple': {
            'handlers': ['console', 'file'],
            'level': 'WARN',
        }
    }
}

logging.config.dictConfig(config)


print 'logger:'
logger = logging.getLogger('root')

logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')


print 'logger2:'
logger2 = logging.getLogger('simple')

logger2.debug('debug message')
logger2.info('info message')
logger2.warn('warn message')
logger2.error('error message')
logger2.critical('critical message')

注:

日志的严重等级

Log Level如下,严重等级为NOTSETDEBUGINFOWARNINGERRORCRITICAL, 严重程度依次递增

CRITICAL: 50
ERROR: 40
WARNING: 30
INFO: 20
DEBUG: 10
NOTSET: 0

修改日志消息的格式

日志的默认显示格式为:%(asctime)s - %(name)s - %(levelname)s - %(message)s,如果只想显示日志等级和日志信息,可以把格式改为:%(levelname)s:%(message)s,想了解全部Formatter中的可用变量,请查阅LogRecord attributes

日期时间的默认格式是ISO8601,修改日期时间格式请参考 time.strftime()

分享到:
评论

相关推荐

    Python-CrawlJobble伯乐在线全站爬虫

    【Python-CrawlJobble伯乐在线全站爬虫】是一个基于Python编程语言的网络爬虫项目,主要用于抓取伯乐在线网站的全站数据。这个爬虫程序可以帮助开发者或者数据分析人员收集、整理伯乐在线上的各类信息,如职位招聘...

    利用python分析access日志的方法

    整体来看,本文介绍了利用Python实现对access日志的自动化分析过程,核心在于处理大量数据的日志文件,通过编写脚本快速定位并记录可能的Web攻击行为。这一过程涵盖了使用正则表达式匹配特定模式的字符串、合并文件...

    Python库 | humanfriendly-3.4.1.tar.gz

    本篇文章将深入探讨这个库的特性、功能以及在实际应用中的价值。 humanfriendly库是Python社区中一个非常实用的工具,它的主要目标是使与人类可读的数据格式进行交互变得更加简单。这个库的名字就已经揭示了它的...

    python装饰器练习题及答案

    在本篇文章中,我们将探讨三个关于Python装饰器的练习题,并深入理解它们的工作原理和应用。 首先,我们来看第一个装饰器练习。目标是创建一个装饰器,用于在多个函数上添加认证功能。这里我们定义了一个名为`login...

    python+appium+yaml移动端自动化测试框架实现详解

    不想看文章得可以直接去Github,欢迎拍砖 大致结构如下: testyaml管理用例,实现数据与代码分离,一个模块一个文件夹 public 存放公共文件,如读取配置文件、启动appium服务、读取Yaml文件、定义日志格式等 page ...

    基于onnxruntime部署MOWA多合一图像扭曲模型C++和Python两个版本源码+模型+测试图片.zip

    起初想用opencv-dnn做推理引擎的,可是opencv-dnn加载onnx文件报错了,看日志信息推测是在encoder模块里的LeWinTransformerBlock模块里的masked_fill在捣鬼 ,因此我使用onnxruntime做推理引擎。

    g_tensorflow_zip_

    首先,我们来看“train”和“test”这两个关键词。在机器学习流程中,训练(train)是指使用已标记的数据调整模型参数以最小化损失函数的过程。测试(test)则是指在未见过的数据上评估模型性能,以确保其泛化能力。...

    统计大文件中各个字符的数量(中文、英文、数字)

    在IT行业中,处理大文件是一项常见的任务,尤其是在数据挖掘、日志分析或文本处理等领域。当我们需要统计大文件中各种字符(包括中文、英文、数字)的数量时,往往需要采用有效的策略来提高效率。本篇文章将详细介绍...

    基于SIP开发软件电话的一些资源(转自YOUTOO)

    由于oSIP是比较底层的SIP协议栈实现,新手较难上手,而官方的示例大都是一些伪代码,需要有实际的例子程序参考学习,而最好的例子就是同样官方发布的oSIP的扩展开发库exosip2,使用exoSIP可以很...

    C#源码做的新浪博客采集器,仅供C#学习用

    10. **持续学习和更新**:由于网络环境和技术的不断变化,开发者需要保持对新技术和新策略的关注,如了解新的反爬策略,学习更高效的爬虫框架如Scrapy(Python)或AngleSharp(C#)。 通过这个项目,C#学习者不仅...

    k8s-mastery:文章“在3小时内学习Kubernetes”的存储库

    2. **Kubernetes**:已经解释过,是容器编排工具。 3. **Microservices**:一种软件开发架构风格,将大型应用分解为一组小型、独立的服务,每个服务都专注于完成特定业务功能。 4. **Spring Boot**:Java平台上的轻...

    pycharm运行程序时看不到任何结果显示的解决

    ### PyCharm运行程序时看不到任何结果显示的解决办法 在使用PyCharm开发Python应用程序时,可能会遇到程序运行后没有输出任何结果的情况。这可能是由于多种原因造成的,本文将详细介绍几种常见的解决方法。 #### ...

    代码之美(中文完整版).pdf

    第18章 Python的字典类:如何打造全能战士 18.1. 字典类的内部实现 18.2. 特殊调校 18.3. 冲突处理 18.4. 调整大小 18.5. 迭代和动态变化 18.6. 结论 18.7. 致谢 第19章 NumPy中的多维迭代器 19.1 N维数组操作中的...

    Openstack 启动instance 'hvm'错误问题解决办法

    错误日志提示了一个Traceback,这通常意味着Python代码中出现了未处理的异常,导致程序中断。 针对这样的错误,一般我们采取以下步骤来解决问题: 1. 查看完整的错误信息和Traceback,确定问题发生的具体位置和可能...

    PHP基础教程 是一个比较有价值的PHP新手教程!

    出处:风流的CG网络日志 时间:Mon, 28 Aug 2006 07:24:34 +0000 作者:yufeng 地址:http:///read.php?38 内容: 提供给新手学习的 PHP新手教程,是一个比较有价值的PHP新手教程! 一、PHP简介 PHP是一种易于...

    GenNEXTScrape:下一代网站的抓取网站

    虽然GenNEXTScrape功能强大,但使用时必须遵循各国家和地区对于数据抓取的法律法规,尊重网站的robots.txt协议,避免对目标网站造成过大负担,确保抓取活动的合法性与道德性。 通过GenNEXTScrape,开发者和研究...

Global site tag (gtag.js) - Google Analytics