Example Usage
This article contains several examples of simple usage of the logging module. Two additional examples deserve special attention: using multiple handlers or formatters and using logging in multimodule Python applications.
本文包含了几个使用logging模块的简单例子.另外两个例子应该额外注意:使用多handlers多formatters和在多Python应用中使用logging的例子.
Multiple handlers and formatters
Loggers are plain Python objects. The addHandler() method has no minimum or maximum quota for the number of handlers you may add. Sometimes it will be beneficial for an application to log all messages of all severities to a text file while simultaneously logging errors or above to the console. To set this up, simply configure the appropriate handlers. The logging calls in the application code will remain unchanged. Here is a slight modification to the previous simple module-based configuration example:
Loggers是一个简单的Python对象.addHandler()方法没有最多或者最少配额,当你的应用需要在把所有的log信息打到一个txt文件中去,同时又需要把errors级别一上的错误信息打到console时,你就会体会到这个特性的好处.只要简单的配置一下合适的handlers就可以实现这个功能.应用对logging的调用用不着修改.以下是对前一个基于module的配置例子的改进:
#!/usr/bin/env python
import logging
#create logger
logger = logging.getLogger("simple_example")
logger.setLevel(logging.DEBUG)
#create console handler and set level to error
ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)
#create file handler and set level to debug
fh = logging.FileHandler("spam.log")
fh.setLevel(logging.DEBUG)
#create formatter
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s -
%(message)s")
#add formatter to ch and fh
ch.setFormatter(formatter)
fh.setFormatter(formatter)
#add ch and fh to logger
logger.addHandler(ch)
logger.addHandler(fh)
#"application" code
logger.debug("debug message")
logger.info("info message")
logger.warn("warn message")
logger.error("error message")
logger.critical("critical message")
Notice that the "application" code did not change between the single-handler example and this one. All that changed was the addition and configuration of a new handler named fh.
你可以看到,在单handler例子和这个例子之间应用的代码根本不需要修改.需要做的仅仅是增加一些代码并且添加一个叫fh的handler.
The ability to create new handlers with higher- or lower-severity filters can be very helpful when writing and testing an application. How many times have I written a horde of print statements in a section of code as I was trying to hammer something out, only to comment it out later? A better approach, which also opens the door for later troubleshooting, is to use logger.debug instead of print. Unlike the print statements, which you will have to delete or comment out later, the logger.debug statements can remain intact in the source code and remain dormant until you need them again. At that time, the only change that needs to happen is to modify the severity level of the logger and/or handler to debug.
在我们写应用或者测试应用的时候,这种根据不同的filter创建不同严重级别的handler的能力可以给我们很大的帮助.为了输出点东西, 我已经记不清有多少次被迫写一堆堆的代码了,一个更好的,对以后可能增加的问题open的解决方案是使用logger.debug来代替print.跟print语句不同,print在用完后必须删除或注释掉,而logger.debug可以留在源码中,并且会保持隐匿的状态,直到你再次的需要它.当你需要它的时候,你可以简单的把logger或者handler的严重级别调为debug级即可.
Using logging in multiple modules
I mentioned above that multiple calls to logging.getLogger('someLogger') return a reference to the same logger object. This is true not only within the same module, but also across modules as long as it is in the same Python interpreter process. It is true for references to the same object; additionally, application code can define and configure a parent logger in one module and create (but not configure) a child logger in a separate module, and all logger calls to the child will pass up to the parent. Here is a main module:
上面我曾提到过,所有的对logging.getLogger(‘someLogger’)的调用都会返回同一个对象.这个规则不仅仅在同一个module有效,而且对在同一个Python的解释器进程里面的多个module也有效.而且,应用代码可以在一个module里面定义一个父logger,而在另一个module里面继承这个logger,所有对这个子logger的调用都会转到父logger里面去,如下所示:
#!/usr/bin/env python
import logging
import auxiliary_module
#create logger with "spam_application"
logger = logging.getLogger("spam_application")
logger.setLevel(logging.DEBUG)
#create file handler and set level to debug
fh = logging.FileHandler("spam.log")
fh.setLevel(logging.DEBUG)
#create console handler and set level to error
ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)
#create formatter
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s -
%(message)s")
#add formatter to fh
fh.setFormatter(formatter)
#add formatter to ch
ch.setFormatter(formatter)
#add fh to logger
logger.addHandler(fh)
#add ch to logger
logger.addHandler(ch)
logger.info("creating an instance of auxiliary_module.Auxiliary")
a = auxiliary_module.Auxiliary()
logger.info("created an instance of auxiliary_module.Auxiliary")
logger.info("calling auxiliary_module.Auxiliary.do_something")
a.do_something()
logger.info("finished auxiliary_module.Auxiliary.do_something")
logger.info("calling auxiliary_module.some_function()")
auxiliary_module.some_function()
logger.info("done with auxiliary_module.some_function()")
Here is the auxiliary module:
这是辅助模块的代码:
#!/usr/bin/env python
import logging
#create logger
module_logger = logging.getLogger("spam_application.auxiliary")
class Auxiliary:
def __init__(self):
self.logger = logging.getLogger("spam_application.auxiliary.Auxiliary")
self.logger.info("creating an instance of Auxiliary")
def do_something(self):
self.logger.info("doing something")
a = 1 + 1
self.logger.info("done doing something")
def some_function():
module_logger.info("received a call to \"some_function\"")
The output looks like this:
输出如下:
2005-03-23 23:47:11,663 - spam_application - INFO -
creating an instance of auxiliary_module.Auxiliary
2005-03-23 23:47:11,665 - spam_application.auxiliary.Auxiliary - INFO -
creating an instance of Auxiliary
2005-03-23 23:47:11,665 - spam_application - INFO -
created an instance of auxiliary_module.Auxiliary
2005-03-23 23:47:11,668 - spam_application - INFO -
calling auxiliary_module.Auxiliary.do_something
2005-03-23 23:47:11,668 - spam_application.auxiliary.Auxiliary - INFO -
doing something
2005-03-23 23:47:11,669 - spam_application.auxiliary.Auxiliary - INFO -
done doing something
2005-03-23 23:47:11,670 - spam_application - INFO -
finished auxiliary_module.Auxiliary.do_something
2005-03-23 23:47:11,671 - spam_application - INFO -
calling auxiliary_module.some_function()
2005-03-23 23:47:11,672 - spam_application.auxiliary - INFO -
received a call to "some_function"
2005-03-23 23:47:11,673 - spam_application - INFO -
done with auxiliary_module.some_function()
Conclusion
logging was a great addition to the standard library. It provides application developers a simple, single interface for outputting information from a running application. On the very simple end, it can write information to a standard log file. On the more advanced end, it can write the same information to a socket--and it can do both without having to rewrite a single line of application code or even restart the process. So the next time you start to put a bunch of print statements in your code to debug something, consider using logging--specifically, logger.debug(). You won't be disappointed.
Logging模块是对原有标准库的一个非常棒的补充.有了它,应用程序就可以通过一个简单的,单一的接口在运行时输出信息.最基本地,它可以输出信息到一个标准的log文件;高级地,它可以把这些信息输出到一个socket—更棒地是它可以同时做这两件事情,并且不需要改动应用的代码甚至都不需要重启引用的进程~!.所以,下次当你想用一堆print语句来debug什么的时候,考虑一下logging—特别是logger.debug()方法.你绝对不会失望地~!