最近有这样一个需求,需要记录一下用户行为,和记下一些错误日志,放入指定文件夹里不同的文件下,方便后续debug。我决定采用python logging模块。并且使用配置文件,并做一个全局的globalLog.py来使用logging。 (关键词:logging,TimedRotatingFileHandler)
——————————————第一步——————————————
添加配置文件logger_config.ini。文件的后缀名其实无所谓,conf,ini或者别的都行。我把该文件放置在/{$项目名}/resource/路径下。
重点1:TimedRotatingFileHandler用来配置log的滚动删除,arg里的"midnight", 1, 6,'utf-8' 表示“每一天午夜12点将当天的日志转存到一份新的日志文件中,并且加上时间戳后缀,最多保存6个文件,编码格式UTF-8,支持中文”
重点2:如果要同时输出到2个文件和屏幕上,那么需要使用三个handler,2个为TimedRotatingFileHandler,还有1个是StreamHandler
重点3:level级别如下,级别越低,打印的日志越详细,例如级别为noset,则会打印出所有信息,如果级别为info,那么不会打印出debug信息。我们的例子中,级别为info,日志里不会打印出debug的信息
下面是详细的配置文件: [loggers] keys=root [handlers] keys=rotatingFileHandler,streamHandler,errorHandler [formatters] keys=simpleFmt [logger_root] level=DEBUG handlers=rotatingFileHandler,streamHandler,errorHandler [handler_rotatingFileHandler] class=handlers.TimedRotatingFileHandler level=INFO formatter=simpleFmt args=(os.path.abspath(os.getcwd() + "/resource/ta_log/default.log"),"midnight", 1, 6,'utf-8') [handler_errorHandler] class=handlers.TimedRotatingFileHandler level=ERROR formatter=simpleFmt args=(os.path.abspath(os.getcwd() + "/resource/ta_log/error.log"), "midnight", 1, 6,'utf-8') [handler_streamHandler] level=INFO class=StreamHandler formatter=simpleFmt args=(sys.stdout,) [formatter_simpleFmt] format=%(asctime)s %(pathname)s(%(lineno)d): %(levelname)s %(message)s
——————————————第二步——————————————
编写globalLog.py 作为全局log的管理入口。
后续别的模块下的python文件需要使用日志功能时,需要导入该模块。该模块的原理也很简单,定位到文件路径,然后通过logger的名字获得要用的logger配置,例如我上面的配置文件中 [loggers] keys=root 所以这里就用了root.然后创建一个全局的logger对象,命名为ta_log
#globalLog.py import logging import logging.config import os def get_logger(name='root'): conf_log = os.path.abspath(os.getcwd() + "/resource/logger_config.ini") logging.config.fileConfig(conf_log) return logging.getLogger(name) ta_log = get_logger(__name__)
——————————————第三步——————————————
在需要打印日志的地方使用该方法,例如在main.py里通过ta_log.info()打印日志。该方法会打印各个级别的信息进入两个日志文件中。我们在第四步来看一看日志文件的内容
import sys from globalLog import ta_log if __name__ == '__main__': ta_log.info("start") try: print(1 / 0) except Exception: ta_log.error("error:") ta_log.exception(sys.exc_info()) ta_log.debug("end")
——————————————第四步——————————————
运行程序,检查日志文件。 这是default.log,级别是info.没有记录ta_log.debug()的信息
2018-08-31 13:09:34,928 C:/lzw_programming/test/main.py(6): INFO start 2018-08-31 13:09:34,928 C:/lzw_programming/test/main.py(10): ERROR error: 2018-08-31 13:09:34,930 C:/lzw_programming/test/main.py(11): ERROR (<type 'exceptions.ZeroDivisionError'>, ZeroDivisionError('integer division or modulo by zero',), <traceback object at 0x0000000003B38888>) Traceback (most recent call last): File "C:/lzw_programming/test/main.py", line 8, in <module> print(1 / 0) ZeroDivisionError: integer division or modulo by zero
这是error.log。级别是error。没有记录ta_log.info()和ta_log.debug()的信息
2018-08-31 13:09:34,928 C:/lzw_programming/testassist/main.py(10): ERROR error: 2018-08-31 13:09:34,930 C:/lzw_programming/testassist/main.py(11): ERROR (<type 'exceptions.ZeroDivisionError'>, ZeroDivisionError('integer division or modulo by zero',), <traceback object at 0x0000000003B38888>) Traceback (most recent call last): File "C:/lzw_programming/testassist/main.py", line 8, in <module> print(1 / 0) ZeroDivisionError: integer division or modulo by zero
——————————————第五步——————————————
运行了3天主程序,查看是否滚动产生了新的日志信息,结果是把历史日志信息滚动复制到了新的文件里,后缀名为日期,如图。