这篇文章主要参考: http://victorlin.me/posts/2012/08/26/good-logging-practice-in-python

==========================
应用程序的logging的做法
==========================
1. 对于主模块, 直接对root logger做logger输出设置. 这样所有模块都会按照root logger的设置进行log 输出.
2. 所有模块, 包括主模块, 都应使用logging.getLogger(__name__)来获得logger实例, 使用getLogger(__name__)获得的logger, 输出的日志能体现出模块的命名空间. 主模块getLogger()调用应放在logging初始化之后.
3. 对于非主模块,不应做logger的初始化配置, 也不应该在模块级上调用getLogger(), 而应该在function中或者class中来调用getLogger().
理由是: 最主要的原因是, log配置应该是主模块的特权. 还有一个理由是, 我们的主module往往是先import非主module, 然后再用logging.config.fileConfig()做初始化, 而fileConfig()缺省会disable已存在的所有logger, 也就是说非主模块级别的那些logger都被禁掉了, 也就无法再用来记日志.
4. 在主模块和非主模块推荐, 都应该使用logger.info()和logger.debug()来记日志, 不推荐使用logging.info()和logging.debug()这样的方法, 后者是用的是root logger, 所有模块都用root, 就无法区分日志是由哪个模块产生的了.
5. 推荐使用 cloghandler.py 的 ConcurrentRotatingFileHandler.
   而不是FileHandler 和RotatingFileHandler 和TimedRotatingFileHandler .  
   理由是 FileHandler, 单文件日志缺点比较多.  
   而 RotatingFileHandler的问题是, 在windows下当文件大小到达max时, logging操作会报错, 新log有时候就记不进去了. 另外如果多个程序往同一个log文件写, RotatingFileHandler也会报错的, cloghandler.py没这个问题.

而TimedRotatingFileHandler的问题是, 在windows下, 如果log文件在23:59正在被写入, logging操作也会报错, 无法进行log文件重命名, 新log有时候就记不进去了. 当然这个几率要比RotatingFileHandler失败几率小.

参考 http://pydoc.net/Python/cloud/2.3.9/cloud.util.cloghandler.cloghandler/
6. 长log的format, 我使用的是,
   说明: 前面加上####, 这样log parser容易分开不同的log记录. 分隔符使用|而不是逗号, 因为时间串中会包含个逗号的.
   formatter = logging.Formatter(fmt='####%(asctime)s|pid=%(process)d|tid=%(thread)d|%(name)s|%(levelname)s|%(message)s')
   短log的format, 我使用的是,
   shortFormatter = logging.Formatter(fmt='####%(asctime)s|%(name)s|%(levelname)s|%(message)s', datefmt="%H:%M:%S")
7. 关于应用程序如何合并第3方类库的log输出, 比如合并SqlAlchemy的日志.
   基本不用特别在意, 只要我们的程序设置了root logger, 应用程序和SqlAlchemy的日志自然会合并输出在root logger的handler中.

==========================   
类库的logging的做法
==========================
1.类库logging的使用, 其实和application的非主模块类似.
2.在类库的top level库中, 最好为logger加上NullHandler, 这样即使应用程序根本没做logging配置, 也不会出现未配置logging的警告信息.

==========================
几个有关的函数
==========================
rootLogger = logging.getLogger() #getLogger()不带参数, 得到的即是rootLogger
logging.basicConfig(level=logging.DEBUG) #是一个很顺手的logging配置方案, 输出为stderr, 非常适合在demo和调试程序

logging.config.dictConfig(dict_LOG_CONFIG) #使用dict来初始化logger

logging.config.fileConfig(ini_file) #使用ini文件来初始化logger

==========================
选择合适的logging level
==========================
这里误区也比较多, 很多程序员喜欢滥用error级别. 可最佳日志实践中的介绍,
http://www.bitstech.net/2014/01/07/log-best-practice/
DEBUG : 开发人员debug用, 比如记录详尽的业务动作, 比如SQL
INFO  : 记录一些关键的动作和数据.  
WARN  : 用于那些对业务功能已有影响, 但不太严重的情形
ERROR : 仅用于记录那些已影响业务功能的Error或Exception
FATAL : (同CRITICAL)仅用于影响到程序完全不能工作的情况, 比如非法退出
如果还不容易区分, 换另一个角度, WARNING和ERROR级别的问题, 都是需要及时处理.

==========================   
dict 配置的写法
==========================   
  1. 具体 ini 配置文件如何写, 参考<python日志不完全指南> http://cjs.linuxapp.org/?p=116  
  2. dict 配置, 后面有个sample.    
dict_LOG_CONFIG ={
    #版本总是1
    'version': 1,  
    #     
    'disable_existing_loggers': False,
    'formatters': {
        'standard': {
            'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
        },
    },
    'handlers': {
        'default': {
            'level':'INFO',    
            'class':'logging.StreamHandler',
        },  
    },
    'loggers': {
        
        #加一个root logger        
        '': {                  
            'handlers': ['default'],        
            'level': 'INFO',  
            'propagate': True  
        },
        
        #加其他logger
        'django.request': {
            'handlers': ['default'],
            'level': 'WARN',  
            'propagate': False
        },
    }
}
   
   
   
==========================   
ini 配置的写法
==========================   
 参考<python日志不完全指南> http://cjs.linuxapp.org/?p=116   
# 定义logger模块,root是必需的,其它的是自定义。
[loggers]
keys=root, web.debug, web.info, web.error

# 定义格式化输出
[formatters]
keys=simpleFormatter, webSimpleFormatter

# 定义handler
[handlers]
keys=consoleHandler,rotateFileHandler, webDebugRotateFileHandler, webInfoRotateFileHandler, webErrorRotateFileHandler, webSMTPHandler

#--------------------------------------------------
# 实现上面定义的logger模块,必需是[logger_xxxx]这样的形式
#--------------------------------------------------
# [logger_xxxx] logger_模块名称
# level     级别,级别有DEBUG、INFO、WARNING、ERROR、CRITICAL
# handlers  处理类,可以有多个,用逗号分开
# qualname  logger名称,应用程序通过 logging.getLogger获取。对于不能获取的名称,则记录到root模块。
# propagate 是否继承父类的log信息,0:否 1:是
[logger_root]
level=DEBUG
handlers=consoleHandler,rotateFileHandler

[logger_web.debug]
level=DEBUG
handlers=consoleHandler,webDebugRotateFileHandler
qualname=web.debug
propagate=0

[logger_web.info]
level=INFO
handlers=consoleHandler,webInfoRotateFileHandler
qualname=web.info
propagate=0

[logger_web.error]
level=ERROR
handlers=consoleHandler,webErrorRotateFileHandler,webSMTPHandler
qualname=web.error
propagate=0

#--------------------------------------------------
# 日志格式
#--------------------------------------------------
# %(asctime)s       年-月-日 时-分-秒,毫秒 2013-04-26 20:10:43,745
# %(filename)s      文件名,不含目录
# %(pathname)s      目录名,完整路径
# %(funcName)s      函数名
# %(levelname)s     级别名
# %(lineno)d        行号
# %(module)s        模块名
# %(message)s       消息体
# %(name)s          日志模块名
# %(process)d       进程id
# %(processName)s   进程名
# %(thread)d        线程id
# %(threadName)s    线程名
[formatter_simpleFormatter]
format=%(asctime)s|%(name)s|%(threadName)s|%(levelname)s > %(message)s

[formatter_webSimpleFormatter]
format=%(asctime)s %(clientip)s %(levelname)s > %(message)s

#--------------------------------------------------
# handler
#--------------------------------------------------
# [handler_xxxx]
# class handler类名
# level 日志级别
# formatter,上面定义的formatter
# args handler初始化函数参数
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)

[handler_rotateFileHandler]
class=handlers.RotatingFileHandler
level=DEBUG
formatter=simpleFormatter
args=('access.log','a',2000000,9)

[handler_webDebugRotateFileHandler]
class=handlers.RotatingFileHandler
level=DEBUG
formatter=simpleFormatter
args=('debug.log','a',2000000,9)

[handler_webInfoRotateFileHandler]
class=handlers.RotatingFileHandler
level=INFO
formatter=webSimpleFormatter
args=('info.log','a',2000000,9)

[handler_webErrorRotateFileHandler]
class=handlers.RotatingFileHandler
level=ERROR
formatter=webSimpleFormatter
args=('error.log','a',2000000,9)

[handler_webSMTPHandler]
class=handlers.SMTPHandler
level=ERROR
formatter=webSimpleFormatter
args=('mailhost', 'fromaddr', ('toaddrs1','toaddrs2'), 'subject', ('username','password'))

正确使用Python logging的更多相关文章

  1. Python logging 模块和使用经验

    记录下常用的一些东西,每次用总是查文档有点小麻烦. py2.7 日志应该是生产应用的重要生命线,谁都不应该掉以轻心 有益原则 级别分离 日志系统通常有下面几种级别,看情况是使用 FATAL - 导致程 ...

  2. python logging模块可能会令人困惑的地方

    python logging模块主要是python提供的通用日志系统,使用的方法其实挺简单的,这块就不多介绍.下面主要会讲到在使用python logging模块的时候,涉及到多个python文件的调 ...

  3. python logging 配置

    python logging 配置 在python中,logging由logger,handler,filter,formater四个部分组成,logger是提供我们记录日志的方法:handler是让 ...

  4. Python LOGGING使用方法

    Python LOGGING使用方法 1. 简介 使用场景 场景 适合使用的方法 在终端输出程序或脚本的使用方法 print 报告一个事件的发生(例如状态的修改) logging.info()或log ...

  5. python logging 日志轮转文件不删除问题

    前言 最近在维护项目的python项目代码,项目使用了 python 的日志模块 logging, 设定了保存的日志数目, 不过没有生效,还要通过contab定时清理数据. 分析 项目使用了 logg ...

  6. python logging模块使用

    近来再弄一个小项目,已经到收尾阶段了.希望加入写log机制来增加程序出错后的判断分析.尝试使用了python logging模块. #-*- coding:utf-8 -*- import loggi ...

  7. python Logging的使用

    日志是用来记录程序在运行过程中发生的状况,在程序开发过程中添加日志模块能够帮助我们了解程序运行过程中发生了哪些事件,这些事件也有轻重之分. 根据事件的轻重可分为以下几个级别: DEBUG: 详细信息, ...

  8. Python logging日志系统

    写我小小的日志系统 配置logging有以下几种方式: 1)使用Python代码显式的创建loggers, handlers和formatters并分别调用它们的配置函数: 2)创建一个日志配置文件, ...

  9. python logging模块使用流程

    #!/usr/local/bin/python # -*- coding:utf-8 -*- import logging logging.debug('debug message') logging ...

随机推荐

  1. wpf中textbox与textblock有什么区别

    textbox是windows.form控件,textblock是WPF控件. 功能类似,但后者功能更强,也节省系统资源 wpf是基于directx技术的系统,向后兼容性更好. textblock只用 ...

  2. IE的layout属性详解

    http://www.cnblogs.com/yuzhongwusan/archive/2012/03/09/2387052.html 很多在谷歌浏览器(chrome).火狐浏览器(Fire Fox) ...

  3. shell处理mysql增、删、改、查

    引言     这几天做一个任务,比对两个数据表中的数据,昨天用PHP写了一个版本,但考虑到有的机器没有php或者php没有编译mysql扩展,就无法使用mysql系列的函数,脚本就无效了,今天写个sh ...

  4. 基本概率分布Basic Concept of Probability Distributions 2: Poisson Distribution

    PDF version PMF A discrete random variable $X$ is said to have a Poisson distribution with parameter ...

  5. resultset 对象获取行字段数据时报:java.sql.SQLException: Column 'id' not found.

    resultset 对象获取行字段数据时报:java.sql.SQLException: Column 'id' not found. 代码: String sql="SELECT d.co ...

  6. 05.K米评测

    体验产品:K米Android版本 软件版本:4.3.0 设备型号:魅蓝note2 操作系统: Android5.1 体验时间:2016.10.15-2016.10.15 体验人:黄瑞钰(0314025 ...

  7. C语言函数指针的用法

    函数指针是一种在C.C++.D语言.其他类 C 语言和Fortran 2003中的指针.函数指针可以像一般函数一样,用于调用函数.传递参数.在如 C 这样的语言中,通过提供一个简单的选取.执行函数的方 ...

  8. 捉襟见肘之UIViewAnimationOptions

    [UIView animateWithDuration:duration delay:0.0f options:(curve << | UIViewAnimationOptionBegin ...

  9. MooseFs-分布式文件系统系列(一)之了解并安装它

    preface 在上上家公司,曾维护过公司的MFS文件系统,主要用来存储系统日志文件,单纯的把日志当作文件存储,在当时的架构下,MFS就像一个中间站一样,这边程序生成的日志放入MFS,那边日志分析程序 ...

  10. BZOJ2960: 跨平面

    从一条边出发遍历,每次找旋转角度最小的一条边作为下一条边,直到回到出发的边,就得到了一个区域.这样建出对偶图后跑不定根的最小树形图就行了. #include<bits/stdc++.h> ...