简单的日志输出

import logging

logging.debug('This is debug message.')
logging.info('This is info message.')
logging.warning('This is warning message.')
logging.error('This is error message.')
logging.critical('This is critical message.')
# Output in stdout:

# WARNING:root:This is warning message.
# ERROR:root:This is error message.
# CRITICAL:root:This is critical message.
import logging

logging.basicConfig(level=logging.INFO,
                    filename='log.log',
                    filemode='w',
                    format='%(levelname)s - %(name)s - %(message)s')

logging.debug('This is debug message.')
logging.info('This is info message.')
logging.warning('This is warning message.')
logging.error('This is error message.')
logging.critical('This is critical message.')

# Output in log.log:

# INFO - root - This is info message. 
# WARNING - root - This is warning message.
# ERROR root - This - is error message.
# CRITICAL - root - This is critical message.

日志等级

日志共有 5 个级别,由高到低分别是 CRITICAL > ERROR > WARNING > INFO > DEBUG

级别 使用
DEBUG 详细信息,调试问题时用到
INFO 表明程序按照预期运行
WARNING 程序出现一些意外,或者在将来可能出现问题,目前程序仍可正常运行
ERROR 程序的部分功能已经不可用
CRITICAL 程序崩溃,已经不能继续运行

几个重要的概念

Logger

import logging

logger = logging.getLogger('foo')
logger.setLevel(logging.INFO)

sh = logging.StreamHandler()
sh.setLevel(logging.INFO)

fmt = logging.Formatter(fmt='%(levelname)s - %(name)s - %(message)s')
sh.setFormatter(fmt)

logger.addHandler(sh)

logger.info('info message')

# INFO - foo - info message

Handler

"""StreamHandler example
"""

import logging
import sys

logger = logging.getLogger('stream')
logger.setLevel(logging.INFO)

sh = logging.StreamHandler(stream=sys.stdout)
sh.setLevel(logging.INFO)

fmt = Formatter(fmt='%(levelname)s:%(name)s:%(message)s')
sh.setFormatter(fmt)

logger.addHandler(sh)
logger.info('info message')

# INFO:stream:info message
"""FileHandler example
"""

import logging

logger = logging.getLogger('file')
logger.setLevel(logging.DEBUG)

fh = logging.FileHandler(filename='log.log', mode='w')
fh.setLevel(logging.DEBUG)

fmt = Formatter('%(name)s - line:%(lineno)d - %s')
fh.setFormatter(fmt)

logger.addHandler(fh)
logger.debug('debug message')

# file - line:16 - debug message
"""RotatingFileHandler example
"""

import logging
import glob
from logging.handlers import RotatingFileHandler

logger = logging.getLogger('rotatingfile')
logger.setLevel(logging.INFO)

rfh = RotatingFileHandler(
        filename='log.out',
        maxBytes=20,
        backupCount=5)

logger.addHandler(rfh)

for i in range(20):
    logger.info('i = {}'.format(i))

logfiles = glob.glob('log.out*')

for filename in logfiles:
    print filename

# log.out
# log.out.1
# log.out.2
# log.out.3
# log.out.4
# log.out.5

Filter

Handler 和 Logger 可以使用 Filter 来完成比级别更复杂的过滤。Filter 基类只允许特定 Logger 层次以下的事件。例如用 ‘A.B’ 初始化的 Filter 允许 Logger ‘A.B’, ‘A.B.C’, ‘A.B.C.D’, ‘A.B.D’ 等记录的事件,logger‘A.BB’, ‘B.A.B’ 等就不行。 如果用空字符串来初始化,所有的事件都接受。

filter = logging.Filter(name='')

Formatter

指定日志记录输出的具体格式。Formatter 的构造方法需要两个参数:消息的格式字符串 fmt 和日期字符串 datefmt,这两个参数都是可选的。

格式 描述
%(name) s 日志名称
%(levelno) s 日志级别数值
%(levelname) s 日志级别
%(pathname) s 当前程序执行路径
%(filename) s 当前执行程序名称
%(module) s 当前模块
%(funcName) s 当前函数名称
%(lineno) d 行号
%(asctime) s 日志时间
%(thread) d 线程 ID
%(threadName) s 线程名称
%(process) d 进程 ID
%(message) s 日志消息

配置

显式配置

# -*- coding: utf-8 -*-

import logging

logger_name = "example"
logger = logging.getLogger(logger_name)
logger.setLevel(logging.DEBUG)

log_path = "./log.log"
fh = logging.FileHandler(log_path)
fh.setLevel(logging.WARN)

fmt = "%(asctime)-15s %(levelname)s %(lineno)d %(process)d %(message)s"
datefmt = "%a %d %b %Y %H:%M:%S"
formatter = logging.Formatter(fmt, datefmt)

fh.setFormatter(formatter)
logger.addHandler(fh)

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

# Thu 06 Apr 2017 16:58:09 WARNING 20 7472 warn message
# Thu 06 Apr 2017 16:58:09 ERROR 21 7472 error message
# Thu 06 Apr 2017 16:58:09 CRITICAL 22 7472 critical message

配置文件

# logging.conf

[loggers]
keys=runner,monitor

[handlers]
keys=runnerHand,monitorHand

[formatters]
keys=defaultForm

[logger_runner]
level=DEBUG
handlers=runnerHand
propagate=0
qualname=runner

[logger_monitor]
level=INFO
handlers=monitorHand
propagate=0
qualname=monitor

[handler_runnerHand]
class=FileHandler
level=DEBUG
formatter=defaultForm
args=('log\\runner.log', 'w')

[handler_monitorHand]
class=FileHandler
level=INFO
formatter=defaultForm
args=('log\\monitor.log', 'w')

[formatter_defaultForm]
format=%(asctime)s - %(levelname)s - %(message)s
# -*- coding: utf-8 -*-

import logging
from logging.config import fileConfig

fileConfig('logging.conf')

if __name__ == '__main__':
    monitor_logger = logging.getLogger('monitor')
    monitor_logger.info('This is monitor log')

    runer_logger = logging.getLogger('runner')
    runer_logger.info('This is runner log')

字典配置

# -*- coding: utf-8 -*-

import logging
from logging.config import dictConfig

logging_conf = dict(
    version=1,
    loggers={
        'runner': {
            'level': logging.INFO,
            'handlers': ['runnerHand'],
            'propagate': 0,
            'qualname': 'runner'
        },
        'monitor': {
            'level': logging.INFO,
            'handlers': ['monitorHand'],
            'propagate': 0,
            'qualname': 'monitor'
        }
    },
    handlers={
        'runnerHand': {
            'class': 'logging.FileHandler',
            'level': logging.INFO,
            'formatter': 'defaultFormatter',
            'filename': 'runner.log',
            'mode': 'w'
        },
        'monitorHand': {
            'class': 'logging.FileHandler',
            'level': logging.INFO,
            'formatter': 'defaultFormatter',
            'filename': 'monitor.log',
            'mode': 'w'
        }
    },
    formatters={
        'defaultFormatter': {
            'format': '%(asctime)s - %(levelname)s - %(message)s'
        }
    }
)

dictConfig(logging_conf)

if __name__ == '__main__':
    monitor_logger = logging.getLogger('monitor')
    monitor_logger.info('This is monitor log')

    runer_logger = logging.getLogger('runner')
    runer_logger.info('This is runner log')


↙↙↙阅读原文可查看相关链接,并与作者交流