这篇文章主要参考: 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. Android成长日记-Android监听事件的方法

    1. Button鼠标点击的监听事件 --setOnClickListener 2. CheckBox, ToggleButton , RadioGroup的改变事件 --setOnCheckedCh ...

  2. Androidstudio 的svn配置 需要忽略的目录

  3. List<List<String>>

    package list; import java.util.ArrayList; import java.util.List; public class MyList { public static ...

  4. MOOCULUS微积分-2: 数列与级数学习笔记 2. Series

    此课程(MOOCULUS-2 "Sequences and Series")由Ohio State University于2014年在Coursera平台讲授. PDF格式教材下载 ...

  5. POJ 2985 The k-th Largest Group(树状数组 并查集/查找第k大的数)

    传送门 The k-th Largest Group Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8690   Acce ...

  6. ArrayList用法

    ArrayList属于collection->List接口下的一个集合类 针对数组的一些缺陷,集合框架提供了ArrayList集合类,对数组进行封装,实现了长度可变的数组,而且和数组彩用相同的存 ...

  7. js中常常容易忘记的基本概念

    javascript组成部分 一个完整的javascript实现应该由三个不同的部分组成:核心(ECMAScript).文档对象模型(DOM).浏览器对象模型(BOM) Web浏览器只是ECMAScr ...

  8. Input Leakage Current

    输入脚一般是的Cmos 的G脚,理论上期望G-S是无限大高阻,,再大的电阻加了电压就会有电流,因为半导体电子迁移,存在微弱电流从G流到S脚.称做漏电流.而其与特定的加载的电压和环境温度有关系. 当然, ...

  9. python 安装包总结

    PIL安装(Centos6.6) 1. 安装PIL所需的系统库 (centos6.6)yum install zlib zlib-devel -yyum install libjpeg libjpeg ...

  10. JS-纯js制作动态成绩表(流程控制语句+js内置对象)

    流程控制for循环+if判断+Math对象+Array对象+Date对象制作成绩表 <!DOCTYPE html><html> <head> <meta ch ...