翻译原文:http://docs.python.org/2/howto/logging.html
略有删减。
基本的Logging教程
程序日志logging是对程序运行时的一些事件进行记录的一种方法。程序员通常调用 logging calls 来标明事件的发生。事件消息包含了程序运行当时的一些变量数据,并且,他还包含了事件本身的重要程度信息,这个重要程度,我们称之为 Level。
一个简单的例子
例子如下:
import logging
logging.warning('Watch out!')#打印一条消息到控制台
logging.info('I told you so')#什么都不会打印
将上述代码写到脚本中并运行,可以看到
打印到控制台中。由于默认的级别是WARNING,所以INFO消息并没有出现。打印出的消息包括,级别、logging调用中事件的描述,即’Watch out!’。目前暂不关心root,后面会给出解释。实际的输出可根据需要灵活的格式化,格式化选项将在后面给出。
记录到文件
通常情形中,需要将日志事件记录到文件。代码如下:
import logging
logging.basicConfig(filename='example.log',level=logging.DEBUG)
logging.debug('This message should go to the log file')
logging.info('So should this')
logging.warning('And this, too')
现在打开文件,就可以看到如下日志记录:
DEBUG:root:This message should go to the log file
INFO:root:So should this
WARNING:root:And this, too
上面的代码还给出了如何设置作跟踪阈值用的日志级别。这里由于阈值是DEBUG,所以所有的消息都打印出来了。
如果你想通过类似下面的命令行选项来设置日志级别:
并且,传递给--log的参数存储在变量loglevel中,可以使用:
getattr(logging, loglevel.upper())
来获取传给函数basicConfig()的参数level的值。可以使用类似下面的例子来对输入的级别值进行错误检查。
# assuming loglevel is bound to the string value obtained from the
# command line argument. Convert to upper case to allow the user to
# specify --log=DEBUG or --log=debug
numeric_level = getattr(logging, loglevel.upper(), None)
if not isinstance(numeric_level, int):
raise ValueError('Invalid log level: %s' % loglevel)
logging.basicConfig(level=numeric_level, ...)
对函数basicConfig()的调用应先于对函数debug(),info()等的调用。由于这种简单配置是一次性的,所以只有第一次调用是有效的,之后的调用则是无效的。
将上面的脚本运行多次后,产生的日志记录都会附加到文件example.log中。如果每次运行都重新开始记录,而不记录之前运行的日志,可以设置filemode参数。修改后如下:
logging.basicConfig(filename='example.log', filemode='w', level=logging.DEBUG)
这里产生的日志跟之前是一样的,但是日志记录不再是附加到文件中,所以之前的记录都丢失了。
日志来自多个模块
如果程序由多个模块构成,下面的例子给出了如何组织日志:
myapp.py 文件:
# 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文件:
# mylib.py
import logging
def do_something():
logging.info('Doing something')
运行myapp.py,将会在文件myapp.log中看到:
INFO:root:Started
INFO:root:Doing something
INFO:root:Finished
而这正是望看到的。mylib.py中使用的方法可以扩展到多个模块的情形。注意,使用这种方法,并不能获知消息来自源码的哪里,除了对事件描述进行对比。如果想跟踪消息的来源,请参见 Advanced Logging Tutorial.
记录数据变量
为了记录数据变量,可以对事件描述信息进行格式化,并将变量作为格式化参数。例如:
import logging
logging.warning('%s before you %s', 'Look', 'leap!')
将会输出:
WARNING:root:Look before you leap!
这里使用了%字符串格式化风格将数据变量合并到了事件描述信息中。这种做法是出于向后兼容考虑:日志包提供了更新的格式化选项str.format()和string.Template。这里不对其展开讨论。
修改消息的格式化选项
修改消息的格式化选项,可以使用类似下面的方法进行指定:
import logging
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)
logging.debug('This message should appear on the console')
logging.info('So should this')
logging.warning('And this, too')
打印结果如下:
DEBUG:This message should appear on the console
INFO:So should this
WARNING:And this, too
这里注意到在前面例子中出现的root消失了。所有可以出现在格式化字符串中的变量集合请参考文档 LogRecord attributes,但是在简单应用中,通产只需要levelname,message(事件描述,包括数据变量),以及事件发生的时间。
显示消息的时间/日期
在格式化字符串中添加%(asctime)s就可以显示事件的时间和日期:
import logging
logging
.basicConfig(format='%(asctime)s %(message)s')
logging.warning('is when this event was logged.')
上述代码会打印出:
2010-12-12 11:41:42,612 is when this event was logged.
默认的日期/时间显示格式是ISO8601。如果需要对日期/时间格式作更多的控制,可以对函数basicConfig的参数datefmt赋值,如下:
import logging
logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
logging.warning('is when this event was logged.')
输出如下所示:
12/12/2010 11:46:36 AM is when this event was logged.
datefmt的格式与time.strftime()支持的格式一致。
下一步
前面给出了一些基本的操作。如果日志需求比较简单,完全可以结合上面给出的例子在自己的脚本使用。