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的, 至少理论上来说是的...