如何使用Python记录当前行和堆栈信息?

pro*_*eek 19 python logging traceback

我有如下记录功能.

logging.basicConfig(
    filename = fileName,
    format = "%(levelname) -10s %(asctime)s %(message)s",
    level = logging.DEBUG
)

def printinfo(string):
    if DEBUG:
        logging.info(string)

def printerror(string):
    if DEBUG:
        logging.error(string)
    print string
Run Code Online (Sandbox Code Playgroud)

我需要登录行号,堆栈信息.例如:

1: def hello():
2:    goodbye()
3:
4: def goodbye():
5:    printinfo()

---> Line 5: goodbye()/hello()
Run Code Online (Sandbox Code Playgroud)

我怎么能用Python做到这一点?

解决了

def printinfo(string):
    if DEBUG:
        frame = inspect.currentframe()
        stack_trace = traceback.format_stack(frame)
        logging.debug(stack_trace[:-1])
    if LOG:
        logging.info(string)
Run Code Online (Sandbox Code Playgroud)

给我这个信息,这正是我需要的.

DEBUG      2011-02-23 10:09:13,500 [
  '  File "/abc.py", line 553, in <module>\n    runUnitTest(COVERAGE, PROFILE)\n', 
  '  File "/abc.py", line 411, in runUnitTest\n    printinfo(string)\n']
Run Code Online (Sandbox Code Playgroud)

Dun*_*can 19

您可以通过更改格式字符串以包含它们来执行当前函数名称,模块和行号.

logging.basicConfig(
    filename = fileName,
    format = "%(levelname) -10s %(asctime)s %(module)s:%(lineno)s %(funcName)s %(message)s",
    level = logging.DEBUG
)
Run Code Online (Sandbox Code Playgroud)

大多数人在记录异常时只需要堆栈,如果调用,日志记录模块会自动执行该操作logging.exception().如果您在其他时间确实需要堆栈信息,则需要使用回溯模块来提取所需的其他信息.


Dun*_*nes 17

import inspect
import traceback

def method():
   frame = inspect.currentframe()
   stack_trace = traceback.format_stack(frame)
   print ''.join(stack_trace)
Run Code Online (Sandbox Code Playgroud)

使用stack_trace [: - 1]可以避免在堆栈跟踪中包含方法/ printinfo.


nco*_*lan 10

从Python 3.2开始,这可以简化为将stack_info=True标志传递给日志记录调用.但是,对于任何早期版本,您都需要使用上述答案之一.

  • 这些文档对此有些冗长。我错过了,谢谢! (2认同)

小智 6

Late answer, but oh well.

Another solution is that you can create your own formatter with a filter as specified in the docs here. This is a really great feature as you now no longer have to use a helper function (and have to put the helper function everywhere you want the stack trace). Instead, a custom formatted implements it directly into the logs themselves.

import logging
class ContextFilter(logging.Filter):
    def __init__(self, trim_amount)
        self.trim_amount = trim_amount
    def filter(self, record):
        import traceback
        record.stack = ''.join(
            str(row) for row in traceback.format_stack()[:-self.trim_amount]
        )
        return True

# Now you can create the logger and apply the filter.
logger = logging.getLogger(__name__)
logger.addFilter(ContextFilter(5))

# And then you can directly implement a stack trace in the formatter.    
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s \n %(stack)s')
Run Code Online (Sandbox Code Playgroud)

注意:在上面的代码中,我修剪了最后 5 个堆栈帧。这只是为了方便,这样我们就不会显示 python 日志记录包本身的堆栈帧。(它也可能需要针对不同版本的日志记录包进行调整)