logging.basicConfig函数各参数: filename: 指定日志文件名 filemode: 和file函数意义相同,指定日志文件的打开模式,'w'或'a' format: 指定输出的格式和内容,format可以输出很多有用信息,如上例所示: %(levelno)s: 打印日志级别的数值 %(levelname)s: 打印日志级别名称 %(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0] %(filename)s: 打印当前执行程序名 %(funcName)s: 打印日志的当前函数 %(lineno)d: 打印日志的当前行号 %(asctime)s: 打印日志的时间 %(thread)d: 打印线程ID %(threadName)s: 打印线程名称 %(process)d: 打印进程ID %(message)s: 打印日志信息 datefmt: 指定时间格式,同time.strftime() level: 设置日志级别,默认为logging.WARNING stream: 指定将日志的输出流,可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,当stream和filename同时指定时,stream被忽略 logging打印信息函数: logging.debug('This is debug message') logging.info('This is info message') logging.warning('This is warning message')
Note:
# 一个logger可以不断增加handler,不会覆盖,所以都有效。 # 这样会导致,一行log重复在多个文件打印,甚至如果不小心,在终端也会打印几遍。 # 解决办法: # 最好在增加handler之前,查看下已有的handler列表 def get_logger(name='', level=logging.DEBUG): logger = logging.getLogger(name) logger.setLevel(level) # console output if len(logger.handlers) == 0: # 避免重复添加 fmt = '%(asctime)-12s - %(levelname)8s - %(message)s' datefmt = '%m-%d %H:%M' fmtt = logging.Formatter(fmt, datefmt) stdHandler = logging.StreamHandler() stdHandler.setFormatter(fmtt) stdHandler.setLevel(logging.DEBUG) logger.addHandler(stdHandler) return logger # logger.handlers 就是已添加到该logger上的handler列表, 它是个list所以,可以遍历它,然后判断每个handler的类型。也可以直接以数量判断,因为添加什么,添加顺序,自己写的程序自己知道。
https://docs.python.org/3/howto/logging.html#logging-basic-tutorial
更多更好的例子:
https://docs.python.org/3/howto/logging-cookbook.html#logging-cookbook
import logging # set up logging to file - see previous section for more details logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', datefmt='%m-%d %H:%M', filename='/temp/myapp.log', filemode='w') # define a Handler which writes INFO messages or higher to the sys.stderr console = logging.StreamHandler() console.setLevel(logging.INFO) # set a format which is simpler for console use
datefmt='%m-%d %H:%M' formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s', datefmt) # tell the handler to use this format console.setFormatter(formatter) # add the handler to the root logger logging.getLogger('').addHandler(console) # Now, we can log to the root logger, or any other logger. First the root... logging.info('Jackdaws love my big sphinx of quartz.') # Now, define a couple of other loggers which might represent areas in your # application: logger1 = logging.getLogger('myapp.area1') logger2 = logging.getLogger('myapp.area2') logger1.debug('Quick zephyrs blow, vexing daft Jim.') logger1.info('How quickly daft jumping zebras vex.') logger2.warning('Jail zesty vixen who grabbed pay from quack.') logger2.error('The five boxing wizards jump quickly.')
When you run this, on the console you will see
root : INFO Jackdaws love my big sphinx of quartz.
myapp.area1 : INFO How quickly daft jumping zebras vex.
myapp.area2 : WARNING Jail zesty vixen who grabbed pay from quack.
myapp.area2 : ERROR The five boxing wizards jump quickly.
and in the file you will see something like
10-22 22:19 root INFO Jackdaws love my big sphinx of quartz. 10-22 22:19 myapp.area1 DEBUG Quick zephyrs blow, vexing daft Jim. 10-22 22:19 myapp.area1 INFO How quickly daft jumping zebras vex. 10-22 22:19 myapp.area2 WARNING Jail zesty vixen who grabbed pay from quack. 10-22 22:19 myapp.area2 ERROR The five boxing wizards jump quickly.
如果你想在多个python 文件中应用相同的logging 配置, 那么只要在主python程序所在的文件中:
# to set the root logger configuration logger = logging.getLogger() # or logger = logging.getLogger('') logger.setLevel(logging.DEBUG) format = '%(asctime)-12s - %(levelname)8s - %(module)s:%(funcName)s:%(lineno)s - %(message)s' fmt = '%(asctime)-12s - %(levelname)8s - %(message)s' formatter = logging.Formatter(format) fmtt = logging.Formatter(fmt) fh = logging.FileHandler(LOG_FILE) fh.setFormatter(formatter) fh.setLevel(logging.DEBUG) logger.addHandler(fh) stdHandler = logging.StreamHandler() stdHandler.setFormatter(fmtt) stdHandler.setLevel(logging.DEBUG) logger.addHandler(stdHandler)