记录代码出错的位置
def f2(b, a):
print(b - a)
def f1(a, b):
return f2(b, a)
def try_log(func, *args, **kwargs):
from time import strftime
from traceback import format_exc
try:
func(*args, **kwargs)
except:
error = format_exc()
print('\033[031m', error, '\033[0m', sep='\n')
with open('%s.log' % strftime('%Y-%m-%d'), 'a', encoding='utf-8') as f:
f.write('%s\n' % error)
if __name__ == '__main__':
try_log(f1, 1, b='2')
分日期保存文件
def write_log(*args):
from time import strftime
ymd = strftime('%Y%m%d')
with open('%s.log' % ymd, 'a', encoding='utf-8') as f:
for i in args:
f.write('%r\n' % i)
f.write('\n')
traceback+写文件
import os
from traceback import format_exc
from time import strftime
_path = os.path.dirname(__file__)
_get_abs_path = lambda path: os.path.normpath(os.path.join(_path, path))
def write_log(*args, **kwargs):
fname = kwargs.pop('fname') if 'fname' in kwargs else'log.txt'
with open(fname, 'a', encoding='utf-8') as f:
for i in args:
f.write('{}\n'.format(i))
print('\033[031m', i, '\033[0m')
for i in kwargs.items():
f.write('{} {}\n'.format(*i))
print('\033[031m', *i, '\033[0m')
f.write('\n')
def traceback_func(func, *args, **kwargs):
try:
value = func(*args, **kwargs)
return value
except:
error = format_exc()
write_log(error, *args, **kwargs)
def remove():
"""清空日志,谨慎启动"""
for fname in os.listdir(_path):
if '.txt' in fname:
abs_fname = _get_abs_path(fname)
print(abs_fname)
os.remove(abs_fname)
if __name__ == '__main__':
remove()
traceback+装饰器
from traceback import format_exc
def write_log(*args, **kwargs):
fname = kwargs.pop('fname') if 'fname' in kwargs else'log.txt'
with open(fname, 'a', encoding='utf-8') as f:
for i in args:
f.write('{}\n'.format(i))
print('\033[031m', i, '\033[0m')
for i in kwargs.items():
f.write('{} {}\n'.format(*i))
print('\033[031m', *i, '\033[0m')
f.write('\n')
def traceback_func(fn):
def function_timer(*args, **kwargs):
try:
result = fn(*args, **kwargs)
return result
except:
error = format_exc().strip()
write_log(error, *args, **kwargs)
return function_timer
def f1(a):
print(int(a))
@traceback_func
def f2(a, *args, **kwargs):
f1(a)
if __name__ == '__main__':
f2('a', fname='a.txt', k='v')

logging模块
format | 中文解释 | remark |
---|
%(message)s | 日志信息 | 必要 |
%(asctime)s | 时间 | 常用 |
%(pathname)s | 绝对路径:sys.argv[0] | 常用 |
%(lineno)d | 行号 | 常用 |
%(funcName)s | 函数名 | 常用 |
%(module)s | 模块名 | 有用 |
%(filename)s | 文件名 | 有用 |
%(relativeCreated)d | 导入logging后的相对时间(毫秒级) | 有用 |
%(created)f | 当前时间:time.time() | 少用 |
%(levelname)s | 日志级别名称,DEBUG、INFO、ERROR…… | 少用 |
%(levelno)s | 日志级别(10, 20, 30, 40, 50) | 少用 |
%(name)s | 日志器名称,默认root | 少用 |
%(process)s | 进程ID | 不用 |
%(processName)s | 进程名称 | 不用 |
%(thread)s | 线程ID | 不用 |
%(thread)s | 线程名称 | 不用 |
%(msecs)d | asctime时间的毫秒部分 | 不用 |
"""
message | %(message)s | 日志信息 | 必要
asctime | %(asctime)s | 时间 | 常用
pathname | %(pathname)s | 绝对路径:sys.argv[0] | 常用
lineno | %(lineno)d | 行号 | 常用
funcName | %(funcName)s | 函数名 | 常用
module | %(module)s | 模块名 | 有用
filename | %(filename)s | 文件名 | 有用
relativeCreated | %(relativeCreated)d | 导入logging后的相对时间(毫秒级) |有用
created | %(created)f | 当前时间:time.time() | 少用
levelname | %(levelname)s | 日志级别名称,DEBUG、INFO、ERROR…… | 少用
levelno | %(levelno)s | 日志级别(10, 20, 30, 40, 50) | 少用
name | %(name)s | 日志器名称,默认root | 少用
process | %(process)s | 进程ID | 不用
processName | %(processName)s | 进程名称 | 不用
thread | %(thread)s | 线程ID | 不用
threadName | %(thread)s | 线程名称 | 不用
msecs | %(msecs)d | asctime时间的毫秒部分 | 不用
"""
import logging, time
logging.basicConfig(level=logging.DEBUG, format=__doc__)
time.sleep(.5)
logger = logging.getLogger('a1')
logger.debug('msg')
打印结果
message | msg | 日志信息 | 必要
asctime | 2020-02-13 16:21:34,550 | 时间 | 常用
pathname | E:/PycharmProjects/anaconda/logger/__init__.py | 绝对路径:sys.argv[0] | 常用
lineno | 25 | 行号 | 常用
funcName | <module> | 函数名 | 常用
module | __init__ | 模块名 | 有用
filename | __init__.py | 文件名 | 有用
relativeCreated | 501 | 导入logging后的相对时间(毫秒级) |有用
created | 1581582094.550740 | 当前时间:time.time() | 少用
levelname | DEBUG | 日志级别名称,DEBUG、INFO、ERROR…… | 少用
levelno | 10 | 日志级别(10, 20, 30, 40, 50) | 少用
name | a1 | 日志器名称,默认root | 少用
process | 4608 | 进程ID | 不用
processName | MainProcess | 进程名称 | 不用
thread | 14292 | 线程ID | 不用
threadName | 14292 | 线程名称 | 不用
msecs | 550 | asctime时间的毫秒部分 | 不用
路径引用示例

日志等级
日志级别名称 | 描述 | 日志级别 |
---|
DEBUG | 调试,最详细的日志信息 | 10 |
INFO | 基本信息(如,打印时间、进度、中间结果、最终结果…) | 20 |
WARNING | 预警信息(如,磁盘可用空间较低),此时应用程序仍正常运行 | 30 |
ERROR | 错误信息,程序某功能不能运行 | 40 |
CRITICAL | 严重错误信息,程序不能运行 | 50 |
- CRITICAL > ERROR > WARNING > INFO > DEBUG
- 默认级别为WARNING(输出大于等于WARNING级别的日志)
四大组件
组件名称 | 对应类名 | 功能描述 |
---|
日志器 | Logger | 提供了应用程序可一直使用的接口 |
处理器 | Handler | 将logger创建的日志记录发送到合适的目的输出 |
过滤器 | Filter | 提供了更细粒度的控制工具来决定输出哪条日志,丢弃哪条日志 |
格式器 | Formatter | 决定日志记录的最终输出格式 |
常用Logger方法
-
Logger.addHandler()
常用Handler
-
logging.StreamHandler:日志打印
logging.FileHandler:日志写入文件
常用Formater参数
-
fmt:格式
datefmt:时间格式
写文件
import logging
logger = logging.getLogger()
sh = logging.StreamHandler()
fh = logging.FileHandler('log.txt', encoding='utf-8')
logger.addHandler(sh)
logger.addHandler(fh)
logger.setLevel(logging.DEBUG)
sh.setLevel(logging.INFO)
fh.setLevel(logging.WARNING)
fmt = logging.Formatter('%(message)s\n%(asctime)s\n%(pathname)s\n%(lineno)d\n')
sh.setFormatter(fmt)
fh.setFormatter(fmt)
class Filter(logging.Filter):
def filter(self, record):
if record.msg is not None:
return True
logger.addFilter(Filter())
if __name__ == '__main__':
logger.info('info')
logger.warning('警告')
logger.error(None)