Python debugging: get filename and line number from which a function is called?

kramer65 picture kramer65 · Jun 26, 2014 · Viewed 18.2k times · Source

I'm currently building quite a complex system in Python, and when I'm debugging I often put simple print statements in several scripts. To keep an overview I often also want to print out the file name and line number where the print statement is located. I can of course do that manually, or with something like this:

from inspect import currentframe, getframeinfo
print getframeinfo(currentframe()).filename + ':' + str(getframeinfo(currentframe()).lineno) + ' - ', 'what I actually want to print out here'

which prints something like:

filenameX.py:273 - what I actually want to print out here

To make it more simple, I want to be able to do something like:

print debuginfo(), 'what I actually want to print out here'

So I put it into a function somewhere and tried doing:

from debugutil import debuginfo
print debuginfo(), 'what I actually want to print out here'
print debuginfo(), 'and something else here'

unfortunately, I get:

debugutil.py:3 - what I actually want to print out here
debugutil.py:3 - and something else here

It prints out the file name and line number on which I defined the function, instead of the line on which I call debuginfo(). This is obvious, because the code is located in the debugutil.py file.

So my question is actually: How can I get the filename and line number from which this debuginfo() function is called? All tips are welcome!

Answer

Zero Piraeus picture Zero Piraeus · Jun 26, 2014

The function inspect.stack() returns a list of frame records, starting with the caller and moving out, which you can use to get the information you want:

from inspect import getframeinfo, stack

def debuginfo(message):
    caller = getframeinfo(stack()[1][0])
    print("%s:%d - %s" % (caller.filename, caller.lineno, message)) # python3 syntax print

def grr(arg):
    debuginfo(arg)      # <-- stack()[1][0] for this line

grr("aargh")            # <-- stack()[2][0] for this line

Output:

example.py:8 - aargh