python中的logging库不是很好用,大概需要这样用:
logging.info("index %d is %s and %s, failed, reason: %s", index, str1, str2, reason);
我怕我把握不住,占位符必须和参数一一对应,不一致或者类型不一致都可能是抛出异常,这样写还会割裂阅读感,占位符形式的日志就是**。
什么样的比较好呢,比如个人习惯这样:
log.info("index:", index, "is", str1, "and", str2, "failed, reason:", reason);
好在哪里呢?不用管参数匹配,不用管参数类型,顺序打印,随时添加修改。
下面就基于python的logging库,封装一个简单符合上述风格的即插即用的log库,贴上完整的代码:
import logging
import os
import inspect
# 日志模块,和print函数风格一致,比占位符模式的logging好用
"""
使用方式举例:
import mylog
a = 100
str = "hello"
mylog.info("a:", a, "str:", str)
output:
YYYY-MM-DD hh:mm:ss INFO [filename:lineno func_name] a: 100 str: hello
"""
# 初始化logging,并输出到控制台
logging.basicConfig(
level=logging.INFO,
filename="log.log",
format='%(asctime)s %(levelname)s %(message)s',
filemode='a',
datefmt='%Y-%m-%d %H:%M:%S')
console = logging.StreamHandler()
console.setLevel(logging.INFO)
formatter = logging.Formatter(
'%(asctime)s %(levelname)s %(message)s')
console.setFormatter(formatter)
logging.getLogger('').addHandler(console)
def getContent(*args, filename, lineno, func):
content = "[" + os.path.split(filename)[-1] + ":" + str(lineno) + " " + func + "]"
for arg in args:
content += " "
content += str(arg)
return content
def info(*args):
lastStackFrame = inspect.currentframe().f_back # 拿到上一个栈帧
logging.info(getContent(*args, filename=lastStackFrame.f_code.co_filename, lineno=lastStackFrame.f_lineno, func=lastStackFrame.f_code.co_name))
def warn(*args):
lastStackFrame = inspect.currentframe().f_back
logging.warn(getContent(*args, filename=lastStackFrame.f_code.co_filename, lineno=lastStackFrame.f_lineno, func=lastStackFrame.f_code.co_name))
def error(*args):
lastStackFrame = inspect.currentframe().f_back
logging.error(getContent(*args, filename=lastStackFrame.f_code.co_filename, lineno=lastStackFrame.f_lineno, func=lastStackFrame.f_code.co_name))
其中inspect主要是为了拿到调用者的文件名、方法名、代码所在行等信息,方便排查问题。