欢迎访问我的博客首页。
Python 日志
- 1. 通过函数调用栈实现
- 2. 改变 print 函数输出字体的颜色
- 3. 使用 logging
- 3.1 自定义名称的句柄
- 3.2 使用默认句柄
- 4. 参考
1. 通过函数调用栈实现
traceback 库记录着 Python 的调用栈。使用 traceback,不仅可以输出日志位置,还可以输出函数调用栈。
import traceback, time, osdef selfLog(*logs, toFile=True):tracebackinfo = str(traceback.extract_stack()[-2])begin = tracebackinfo.index('file')end = tracebackinfo.rindex(' in')tracebackinfo = tracebackinfo[begin:end]times = time.strftime('%Y/%m/%d %H:%M:%S', time.localtime())if toFile:tracebackinfo = 'file ' + os.path.basename(tracebackinfo)handle = open('log.txt', 'a')handle.write('-- log: %s, %s\n' % (tracebackinfo, times))handle.write(' ')for log in logs[:-1]:handle.write('%s ' % log)handle.write('%s\n' % logs[-1])handle.close()returnprint('-- log: %s, %s' % (tracebackinfo, times))print(' ', end='')for log in logs[:-1]:print('%s' % log, end=' ')print(logs[-1])
假如上面的代码在 selfLog.py 中,调用者代码:
from selfLog import selfLog
selfLog('abcd')
selfLog('abc', 'def')
可以看出,我们可以像使用 print 语句一样使用 selfLog:输出单个对象、逗号隔开的多个对象、格式化输出对象。
2. 改变 print 函数输出字体的颜色
python 可以指定 print 字体颜色,代码 selfLog.py:
import config
import time, traceback
from colorama import initinit(autoreset=True)def getColor(rank):manner = 1foreground = 30 # [30, 37]background = 47 # [40, 47]foreground += rank % 8background -= rank % 8# color = '\033[%d;%d;%dm' % (manner, foreground, background)color = '\033[%d;%dm' % (manner, foreground)return colordef selfLog(rank, *logs):if rank < config.selfLogRank:returntracebackinfo = str(traceback.extract_stack()[-2])begin = tracebackinfo.index('file')end = tracebackinfo.rindex(' in')tracebackinfo = tracebackinfo[begin:end]times = time.strftime('%Y/%m/%d %H:%M:%S', time.localtime())print('-- %s, %s' % (tracebackinfo, times))color = getColor(rank)for log in logs:print(' %s%s' % (color, log), end=' ')print()
config.py:
selfLogRank = 0
main.py:
from selfLog import selfLogif __name__ == '__main__':selfLog(1, 'Reading image...', 'info_1', 'info_2')selfLog(3, 'Failed to read image!', 'info_1')
调用时第一个参数 rank 不小于 config.selfLogRank 才会输出。
3. 使用 logging
logging 是 Python 的日志库,可以很方便地把日志输出到控制台或文件中。
使用 logging 库,可以输出单个字符串、数字、变量等对象,但不能输出逗号隔开的多个对象。如果想输出多个对象,需要使用格式化输出。
3.1 自定义名称的句柄
标准库 logging 有一个 logger,该 logger 有一个名称为 root 的默认句柄。句柄负责输出日志,可以通过 logger 添加句柄。
import time
import loggingdef init_log():# 1.变量。date_fmt = '%Y/%m/%d %H:%M:%S'masg_fmt = '%(name)s %(pathname)s, line %(lineno)d, %(asctime)s %(levelname)-5.5s: %(message)s'path_log = time.strftime('%Y%m%d_%H%M%S', time.localtime()) + '.log'# 2.名称为 root 的默认日志。logging.basicConfig(filename='root_' + path_log, filemode='w', format=masg_fmt, datefmt=date_fmt,level=logging.NOTSET)# 3.自定义名称的日志。logger = logging.getLogger('阿尔法公司')# 3.1 控制台。console_handler = logging.StreamHandler()console_handler.setLevel(logging.WARNING)console_handler.setFormatter(fmt=logging.Formatter(fmt=masg_fmt, datefmt=date_fmt))logger.addHandler(console_handler)# 3.2 文件。file_handler = logging.FileHandler(filename=path_log, mode='a', encoding='utf-8')file_handler.setLevel(logging.ERROR)file_handler.setFormatter(fmt=logging.Formatter(fmt=masg_fmt, datefmt=date_fmt))logger.addHandler(file_handler)return loggerif __name__ == '__main__':logger = init_log()logging.info('logging 信息')logging.debug('logging 调试')logging.warning('logging 警告')logging.error('logging 错误')logging.critical('logging 严重错误')logger.info('logger 信息')logger.debug('logger 调试')logger.warning('logger 警告')logger.error('logger 错误')logger.critical('logger 严重错误')
basicConfig 用于配置默认名为 root 的句柄。在这里配置文件名时日志将会被输出到文件,否则输出到控制台。无论使用 logging.info/debug/warning/error/critical 还是 logger.info/debug/warning/error/critical 输出,都会按 basicConfig 的配置输出到文件或控制台。
上面使用 logger 添加的两个自定义句柄,分别把日志输出到控制台和文件。这两个句柄只能响应 logger.info/debug/warning/error/critical,不能响应 logging.info/debug/warning/error/critical。
3.2 使用默认句柄
虽然自定义句柄可以指定名称,但我们必须获取 logger,才能使用它输出。在其它文件中使用 logger,必须先把它 import 进来。使用默认句柄时,只需在项目任意位置配置 logging,在其它文件只需 import logging 就能直接使用。
import time
import loggingdef init_log():# 1.变量。date_fmt = '%Y/%m/%d %H:%M:%S'masg_fmt = '%(name)s %(pathname)s, line %(lineno)d, %(asctime)s %(levelname)-5.5s: %(message)s'path_log = time.strftime('%Y%m%d_%H%M%S', time.localtime()) + '.log'# 2.名称为 root 的默认日志。# logging.basicConfig(filename='root_' + path_log, filemode='w', format=masg_fmt, datefmt=date_fmt,# level=logging.NOTSET)# 3.自定义名称的日志。# logger = logging.getLogger('阿尔法公司')# 3.1 控制台。console_handler = logging.StreamHandler()console_handler.setLevel(logging.WARNING)console_handler.setFormatter(fmt=logging.Formatter(fmt=masg_fmt, datefmt=date_fmt))logging.getLogger().addHandler(console_handler)# 3.2 文件。file_handler = logging.FileHandler(filename=path_log, mode='a', encoding='utf-8')file_handler.setLevel(logging.ERROR)file_handler.setFormatter(fmt=logging.Formatter(fmt=masg_fmt, datefmt=date_fmt))logging.getLogger().addHandler(file_handler)if __name__ == '__main__':init_log()logging.info('logging 信息')logging.debug('logging 调试')logging.warning('logging 警告')logging.error('logging 错误')logging.critical('logging 严重错误')
4. 参考
- print 颜色
- logging 级别,博客园,2019。