专栏名称: 程序员技术
最有影响力的程序员自媒体,关注程序员相关话题:程序人生、IT技术、IT职场、学习资源等。
目录
相关文章推荐
OSC开源社区  ·  升级到Svelte ... ·  2 天前  
程序猿  ·  “我真的受够了Ubuntu!” ·  昨天  
程序员的那些事  ·  成人玩偶 + ... ·  2 天前  
待字闺中  ·  DeepSeek 爆火带来的大变化 ·  1 周前  
51好读  ›  专栏  ›  程序员技术

关于 logging 的一些琐事

程序员技术  · 公众号  · 程序员  · 2018-01-11 19:01

正文

点击上方“ 程序员共读 ”,选择“置顶公众号”

关键时刻,第一时间送达!


虽说 logging 模块都用了好久了,不过由于文档不够详细,每次都忍不住去搜索别人的文章,于是就干脆记录下来吧。

懒得分段了,想到哪写到哪吧。

1.为什么 logging.info() 默认不输出任何东西?

因为默认生成的 root logger 的 level 是 logging.WARNING,低于该级别的就不输出了。可以进行如下设置来输出:


>>> import logging

>>> logging . info ( 'test' )

>>> root_logger = logging . getLogger () # 或使用未公开的 logging.root

>>> root_logger . level

30

>>> logging . getLevelName ( 30 )

'WARNING'

>>> root_logger . level = logging . NOTSET

>>> logging . info ( 'test' )

INFO : root : test


如果还没配置 handler 的话,可以用 logging.basicConfig() 来配置:


>>> root_logger . handlers

[]

>>> logging . basicConfig ( level = logging . NOTSET )

>>> root_logger . handlers

[ < logging . StreamHandler object at 0x108becd10 > ]

>>> logging . info ( 'test' )

INFO : root : test


2.如何定制输出的格式?

给 logger 的 handler 设置一个 logging.Formatter 对象:


>>> root_logger . handlers [ 0 ]. formatter . format

< bound method Formatter . format of < logging . Formatter object at 0x10c062d90 >>

>>> root_logger . handlers [ 0 ]. formatter . datefmt

>>> root_logger . handlers [ 0 ]. formatter . _fmt

'%(levelname)s:%(name)s:%(message)s'

>>> LOGGING_FORMAT = '[%(levelname)1.1s %(asctime)s %(module)s:%(lineno)d] %(message)s'

>>> DATE_FORMAT = '%y%m%d %H:%M:%S'

>>> formatter = logging . Formatter ( LOGGING_FORMAT , DATE_FORMAT )

>>> root_logger . handlers [ 0 ]. formatter = formatter

>>> logging . info ( 'test' )

[ I 130221 01 : 58 : 28 < stdin >: 1 ] test


如果还没配置 handler 的话,可以用 logging.basicConfig() 来配置:


logging . basicConfig (

level = logging . NOTSET ,

format = LOGGING_FORMAT ,

datefmt = DATE _ FORMAT

)


详细的格式介绍就查看文档吧。


3.为什么我重定向了 stdout,但是却看不到输出?

因为默认生成的 root logger 的 handler 的 stream 是 stderr,不是 stdout:


>>> root_logger . handlers [ 0 ]. stream

< open file ' ' , mode 'w' at 0x1089cb270 >


可以如下分别配置:



stdout_handler = logging . StreamHandler ( sys . __stdout__ )

stdout_handler . level = logging . DEBUG

stdout_handler . formatter = formatter

root_logger . addHandler ( stdout_handler )

stderr_handler = logging . StreamHandler ( sys . __stderr__ )

stderr_handler . level = logging . WARNING

stderr_handler . formatter = formatter

root_logger . addHandler ( stderr_handler )



4. 如何将日志输出到文件?

使用 logging.FileHandler():


handler = logging . FileHandler ( 'log/test.log' )

root_logger . addHandler ( handler )


其中文件名可以使用相对路径,但要保证文件夹存在。默认的文件打开方式是 append。
如果还没配置 handler 的话,可以用 logging.basicConfig() 来配置:


logging . basicConfig (

level = logging . NOTSET ,

format = LOGGING_FORMAT ,

datefmt = DATE_FORMAT ,

filename = 'log/test.log' ,

filemode = 'a'

)


5. 捕捉了一个异常,如何输出执行堆栈?
使用 logging.exception(),或在调用 logging.debug() 等方法时加上 exc_info=True 参数。


>>> try :

... 0 / 0

... except :

... logging . exception ( 'Catch an exception.' )

... print '-' * 10

... logging . warning ( 'Catch an exception.' , exc_info = True )

...

ERROR : root : Catch an exception .

Traceback ( most recent call last ) :

File " " , line 2 , in < module >

ZeroDivisionError : integer division or modulo by zero

----------

WARNING : root : Catch an exception .

Traceback ( most recent call last ) :

File " " , line 2 , in < module >

ZeroDivisionError : integer division or modulo by zero


6. 能不能针对不同的用途或模块,指定不同的日志?


可以创建多个 logger:


console_handler = logging . StreamHandler ( sys . __stdout__ )

console_handler . level = logging . DEBUG

console_logger = logging . getLogger ( 'test' )

console_logger . addHandler ( console_handler )

file_handler = logging . FileHandler ( 'log/test.log' )

file_handler . level = logging . WARNING

file_logger = logging . getLogger ( 'test.file' )

file_logger . addHandler ( file_handler )

console_logger . error ( 'test' )

file_logger . error ( 'test' )

console_logger .







请到「今天看啥」查看全文