这篇文章主要参考: 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. Writing a simple Lexer in PHP/C++/Java

    catalog . Comparison of parser generators . Writing a simple lexer in PHP . phc . JLexPHP: A PHP Lex ...

  2. 企业开发中选择logback而不是log4j的理由

    不知道看到这篇文章的Java工程师有没有考虑过这个问题:为什么在企业开发中会选择logback来记录日志,而不是log4j呢? 如果你以前没有考虑过这个问题,那么现在如果让你考虑一下,你可能觉的会是因 ...

  3. 数据结构2 静态区间第K大/第K小

    给定数组$A[1...N]$, 区间$[L,R]$中第$K$大/小的数的指将$A[L...R]$中的数从大到小/从小到大排序后的第$K$个. "静态"指的是不带修改. 这个问题有多 ...

  4. Docker探索系列2之镜像打包与DockerFile

    preface docker基本入门以后,可以试试打包docker镜像与dockerfile了 docker镜像 docker hub仓库有2类仓库,用户仓库和顶层仓库,用户仓库由docker用户创建 ...

  5. Tmux

    常用按键 这里需要说明一点的是,tmux的任何指令,都包含一个前缀,也就是说,你按了前缀(一组按键,默认是Ctrl+b)以后,系统才知道你接下来的指令是发送给tmux的. C-b ? 显示快捷键帮助 ...

  6. php代码加密

    <?php function encode_file_contents($filename) { $type=strtolower(substr(strrchr($filename,'.'),1 ...

  7. ionic的scroll的使用出现的问题

    今天再写ionic的时候发现了一个问题,在使用ui-view的时候引用ion-scroll指令的时候初次加载的时候能能实现拖拽滚动,只能实现滚动鼠标滚轴滚动,然后各种调试,各种比较,终于发现原来是路由 ...

  8. 安装Virtual Box增强功能 - Ubuntu

    一.开发环境 操作系统:Windows 7Virtual Box 版本: 5.0.10 虚拟机系统: Ubuntu 12.04 LTS 二.问题 进入Ubuntu图形界面后,选择“设备” --> ...

  9. LDA(主题模型算法)

    LDA整体流程 先定义一些字母的含义: 文档集合D,topic集合T D中每个文档d看作一个单词序列< w1,w2,...,wn >,wi表示第i个单词,设d有n个单词.(LDA里面称之为 ...

  10. 9月5日网页基础知识 通用标签、属性(body属性、路径、格式控制) 通用标签(有序列表、无序列表、常用标签)(补)

    网页基础知识 一.HTML语言 HTML语言翻译汉语为超文本标记语言. 二.网页的分类 1.静态页面:在静态页面中修改网页内容实际上就是修改网页原代码,不能从后台操作,数据来只能来源于原于代码.静态网 ...