可用于日志格式的调用堆栈
我有一个方法,它可以返回一个简单的调用栈字符串。
def call_stack():
if "inspect" not in globals().keys():
import inspect
stack = [frame[3] for frame in inspect.stack() if frame[3] not in [inspect.stack()[0][3],"<module>"]]
s = ""
for method in stack:
if len(s) > 0:
s += "."
s += method
return s
def modify_logger(logger):
logger.args["call_stack"] = call_stack()
这样做是可能的吗?
import logging
logging.basicConfig(level=logging.DEBUG, format="%(call_stack)s -- %(levelname)s: %(message)s")
def bar():
logging.debug("test")
def foo():
bar()
def monkey():
foo()
# modify root logger.
modify_logger(logging.getLogger())
# write to the log.
monkey()
这会得到以下的结果:
monkey.foo.bar -- DEBUG: test
3 个回答
1
我试了你的解决方案,结合了其他的方法,结果得到了我想要的效果。
import logging
DEBUG = True
TRACE = True
#-----------------------------------------------------------------------------
# TRACE BACK
#-----------------------------------------------------------------------------
class ContextFilter(logging.Filter):
def filter(self, record):
import traceback
if "inspect" not in globals().keys():
import inspect
stack = [frame[3] for frame in inspect.stack()
if frame[3] not in [inspect.stack()[0][3],"<module>"]]
record.stack ='.'.join(reversed(stack))
return True
#----------------------------------------------------------------------- ---------
# LOGGER
#--------------------------------------------------------------------------------
logger = logging.getLogger()
if TRACE:
logger.addFilter(ContextFilter())
if DEBUG:
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(stack)s\n{%(pathname)s:%(lineno)d} - %(asctime)s - %(levelname)s - %(message)s')
fh = logging.FileHandler('log_filename.txt')
fh.setLevel(logging.DEBUG)
fh.setFormatter(formatter)
logger.addHandler(fh)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
ch.setFormatter(formatter)
logger.addHandler(ch)
else:
logger.setLevel(logging.NOTSET)
print 'NOT IN DEBUG MODE: Logging.NOTSET'
1
也许最简单的方法就是定义一个自定义的 debug
函数:
import logging
def call_stack():
if "inspect" not in globals().keys():
import inspect
stack = [frame[3] for frame in inspect.stack()
if frame[3] not in [inspect.stack()[0][3],"<module>"]]
s='.'.join(reversed(stack))
return s
def debug(message):
logging.debug('{s} -- DEBUG: {m}'.format(
s=call_stack()[:-len('debug.')],m=message))
logging.basicConfig(level=logging.DEBUG, format="%(message)s")
def bar():
debug("test")
def foo():
bar()
def monkey():
foo()
monkey()
这样就能得到
monkey.foo.bar -- DEBUG: test
1
昨天我研究了这个模式,发现我想要的在Python语言中并不合理。毕竟,Python是一种解释型语言,这意味着总是有一个文件存在于一个已知的路径下,并且可以引用到某一行。这样的做法在像C#、Java、C或C++这样的编译型语言中是有意义的,因为在这些语言中,你有命名空间、对象和方法,但没有文件/路径和行号的好处。
故事的道理
当有人告诉你你所问的问题没有意义时,不要急着否定他们。花点时间仔细审视一下你最初的请求和你的观点,然后再去追求一个可能在你的特定情况下或背景下并不合理的答案。