Yifei Kong

May 30, 2017

python logging library

Yifei's Notes

Very sad, logging only supports %-style string formatting

logging.exception is the right way to log exceptions, not logging.error

Basic Usage

库只应该定义自己的日志的格式, 而不应该定义自己的日志如何输出, 日志输出应该由最终的使用程序来定义.   如果使用systemd来运行程序的话, 直接把所有日志打印到stdout就可以了

logging.basicConfig(level=level, format=fmt_string, filename=file, datefmt=datefmt)

if you don't supply filename, the log is printed to stdout

logging.debug('%string', args) # send to format string as message
logging messages

logging.getLogger.level = logging.DEBUG
# reset logging level
# basicConfig can only be called once in the main thread

python 的 logging

基本使用

# myapp.py
import logging
import mylib

def main():
    logging.basicConfig(filename='myapp.log', level=logging.INFO)
    logging.info('Started')
    mylib.do_something()
    logging.info('Finished')

if __name__ == '__main__':
    main()
# mylib.py
import logging

def do_something():
    logging.info('Doing something')

If you run myapp.py, you should see this in myapp.log:

INFO:root:Started
INFO:root:Doing something
INFO:root:Finished

进阶教程

logging 模块提供了四种不同的模块

  • Loggers expose the interface that application code directly uses.
  • Handlers send the log records (created by loggers) to the appropriate destination.
  • Filters provide a finer grained facility for determining which log records to output.
  • Formatters specify the layout of log records in the final output.

logger 是一棵树,默认的logger 是 root logger,logging 模块的方法也都是在调用这个logger

Logging in a library

get Logger

by defualt, the logger is called root logger.

You should use the factory method logging.getLogger(name) to instaniate a logger object, the name is supposed to be foo.bar.baz, so the recommnend value is name,That’s because in a module, name is the module’s name in the Python package namespace.

in lib.py

logger = logging.getLogger(name) logger.addHandler(logging.NullHandler())

logger.debug('')

in app.py

logging.basicConfig() # seems like logging.start... must be called to enable logging

turn off 3rd party logs

logging.getLogger("requests").setLevel(logging.WARNING)

import logging

log = logging.getLogger(name)

log.setLevel(logging.INFO) # 设置logger的级别

handler = logging.NullHandler() handler.setLevel(logging.INFO) # 设置handler的级别

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter)

log.addHandler(handler)

日志的作用

Logging serves two purposes: [1] • Diagnostic logging records events related to the application’s operation. If a user calls in to report an error, for example, the logs can be searched for context. • Audit logging records events for business analysis. A user’s transactions can be extracted and combined with other user details for reports or to optimize a business goal.

最佳实践

Here is an example of best practice from the requests source – place this in your init.py import logging logging.getLogger(name).addHandler(logging.NullHandler())

日志应该看作是事件流, 不要自己管理日志, 把日志输出到stdout[2]

[1] http://docs.python-guide.org/en/latest/writing/logging/

logging模块是thread safe的, 至少理论上来说是的...