zoukankan      html  css  js  c++  java
  • python logging

    参考:

    https://docs.python.org/2/howto/logging.html#logging-basic-tutorial

    https://docs.python.org/2/library/logging.config.html#logging-config-api

    https://docs.python.org/2/howto/logging-cookbook.html#logging-cookbook

    http://victorlin.me/posts/2012/08/26/good-logging-practice-in-python

    背景

    Logging 用来追踪程序运行过程中发生的事件, 事件按其重要性可划分为不同的级别: DEBUG, INFO, WARNING, ERROR, CRITICAL.

    • DEBUG            运行中的详细信息, 特别用于代码调试
    • INFO               确认事情按照期待的方式发生了
    • WARNING        一些超出预期的事情发生或将要发生, 但是程序仍可以按照期望的方式继续运行
    • ERROR            发生了更严重的事情, 程序的一些功能会受到影响, 无法进行
    • CRITICAL        程序炸了

    默认的级别是 WARNING, DEBUG 和 INFO 会被忽略.

    输出到终端

    import logging
    
    logging.info("info information")    # will print nothing
    logging.warn("warn infotmation")    # will print a message to the console
    
    Output:
    WARNING:root:warn infotmation

    观察输出, WARNING 是级别, warn infomation 是记录的信息, root是啥? root 是 logger 的名字.

    虽然我们没有显式创建 root logger, root logger 是默认创建的.

    输出到文件

    import logging
    
    logging.basicConfig(filename="example.log", level=DEBUG)
    logging.debug("debug information")
    logging.info("info information")
    logging.error("error information")
    
    
    example.log
    DEBUG:root:debug information
    INFO:root:info information
    ERROR:root:error information

    注意到 basicConfig 方法, 该方法创建一个使用默认 Formatter 的 StreamHandler 并添加到 root logger. 如果 root logger 已经配置了 handler, 调用该方法 will do nothing.

    参数 filename 用来指定日志输出的文件名, 一旦指定了 filename, StreamHandler 不会被创建, FileHandler 会代替 SteamHandler 添加到 root logger.

    名词解释

    Logger        提供应用直接调用的接口

    Handler       将 logger 创建的日志发送到设定的目的地

    Filter           过滤日志, 决定哪些可以输出(暂时用不到, 略)

    Formatter    确定日志最终的输出格式

    Logger

    • Logger.setLevel()    设定级别
    • Logger.addHandler(), Logger.removeHandler()    添加或删除 Handler
    • Logger.addFilter(), Logger.removeFilter()    添加或删除 Filter
    • Logger.debug(), Logger.info(), Logger.warn(), Logger.error(), Logger.critical()
    • Logger.exception()    输出与 Logger.error() 相似, 附加异常详情, 用于异常处理

    Handler

    • Handler.setLevel()    设定级别, 决定是否继续传递
    • Handler.setFormatter()    设定输出格式
    • Handler.addFilter(), Handler.removeFilter()    添加或删除Filter

    Formatter

    • Formatter.__init__(fmt=None, datefmt=None)    datefmt 默认为 "%Y-%m-%d %H:%M:%S" with the milliseconds tacked on at the end, fmt 默认为 "%(levelname)s:%(name)s:%(message)s"

    同时输出到终端和文件, 终端级别为DEBUG, 文件级别为ERROR

    import logging
    
    logger = logging.getLogger(__name__)
    logger.setLevel(level=logging.DEBUG)
    
    formatter = logging.Formatter("%(asctime)s-%(name)s-%(levelname)s-%(message)s")
    
    console = logging.StreamHandler()
    console.setLevel(level=logging.DEBUG)
    console.setFormatter(formatter)
    
    logfile = logging.FileHandler("example.log")
    logfile.setLevel(level=logging.ERROR)
    logfile.setFormatter(formatter)
    
    logger.addHandler(console)
    logger.addHandler(logfile)
    
    logger.debug("debug information")
    logger.info("info information")
    logger.warn("warn information")
    logger.error("error information")
    logger.critical("critical information")
    
    
    Output:
    2016-09-03 23:49:17,207-__main__-DEBUG-debug information
    2016-09-03 23:49:17,207-__main__-INFO-info information
    2016-09-03 23:49:17,207-__main__-WARNING-warn information
    2016-09-03 23:49:17,207-__main__-ERROR-error information
    2016-09-03 23:49:17,207-__main__-CRITICAL-critical information
    
    example.log
    2016-09-03 23:49:17,207-__main__-ERROR-error information
    2016-09-03 23:49:17,207-__main__-CRITICAL-critical information

    logging.FileHandler() 支持相对路径和绝对路径, 习惯上使用绝对路径会好一些

    logging.config.dictConfig

    从字典中读取配置信息, 配置信息可以存储为 json 或 yaml 格式, yaml 更易读, pip install pyyaml

    version: 1
    
    disable_existing_logger: False
    
    formatters:
        brief:
            format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
    
    handlers:
        console:
            class: logging.StreamHandler
            level: DEBUG
            formatter: brief
    
        file:
            class: logging.handlers.RotatingFileHandler
            level: INFO
            formatter: brief
            filename: info.log
            maxBytes: 10500000
            backupCount: 5
            encoding: utf8
    
        mail:
            class: logging.handlers.SMTPHandler
            level: ERROR
            formatter: brief
            mailhost: localhost
            fromaddr: username@test.com
            toaddrs: [receiver0@test.com, receiver1@test.com]
            subject: Program crashed!!!
    
    loggers:
        warthog:
            level: ERROR
            handlers: [file, mail]
            propagate: no
    
    root:
        level: DEBUG
        handlers: [console]

    varsion: 1    必须存在且必须为1

    disable_existing_logger    默认为 True, 会禁用除当前模块的所有 logger

    handlers    console, file, mail 标识不同的 handler, class, level, formatter 指定特定的 Handler, 级别, 输出格式, 其他的参数由不同的 Handler 决定.

    loggers    warthog 标识不同的 logger, 使用方式为 logger.getLogger("warthog"), propagate 默认为 yes, warthog logger 的日志会向上传递到 root logger.

                   如果一个模块叫做 warthog.py, logger = logging.getLogger(__name__), 该 logger 就是 logger warthog

    进阶

    use __name__ as the logger name

    __name__ 是当前模块的名字, 假设当前模块是 foo.bar.my_module, 只要对 logger foo 进行设置, 所有 foo. 中模块的 logger 会自动继承.

    logger.exception

    try:
        open('/path/to/does/not/exist', 'rb')
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as e:
        logger.exception("Failed to open file")
        #logger.error("Failed to open file", exc_info=True)
    
    
    Output:
    
    ERROR:__main__:Failed to open file
    Traceback (most recent call last):
      File "example.py", line 6, in <module>
        open('/path/to/does/not/exist', 'rb')
    IOError: [Errno 2] No such file or directory: '/path/to/does/not/exist'

    Do not get logger at the module level unless disable_existing_loggers is False

    # not good
    import logging
    
    logger = logging.getLogger(__name__)
    
    def foo():
        logger.info("info message")
    
    
    # better
    import logging
    def foo():
        logger = logging.getLogger(__name__)
        logger.info("info message")
  • 相关阅读:
    app测试点
    【Android自动化打包】03. APK的数字签名
    【转】测试架构师团队的管理
    【转】用户体验质量的测试方法论-“你的风扇方案”
    【转】大数据本质与测试
    jquery 获取下拉框值与select text
    js获取下拉,单选
    jquery插件
    加密
    plsql 只能识别32位的oracle解决办法
  • 原文地址:https://www.cnblogs.com/senjougahara/p/5838459.html
Copyright © 2011-2022 走看看