68

In C++, I can print debug output like this:

printf(
   "FILE: %s, FUNC: %s, LINE: %d, LOG: %s\n",
   __FILE__,
   __FUNCTION__,
   __LINE__,
   logmessage
);

How can I do something similar in Python?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
pengdu
  • 1,331
  • 2
  • 14
  • 21

10 Answers10

94

There is a module named inspect which provides these information.

Example usage:

import inspect

def PrintFrame():
  callerframerecord = inspect.stack()[1]    # 0 represents this line
                                            # 1 represents line at caller
  frame = callerframerecord[0]
  info = inspect.getframeinfo(frame)
  print(info.filename)                      # __FILE__     -> Test.py
  print(info.function)                      # __FUNCTION__ -> Main
  print(info.lineno)                        # __LINE__     -> 13

def Main():
  PrintFrame()                              # for this line

Main()

However, please remember that there is an easier way to obtain the name of the currently executing file:

print(__file__)
CodeMonkey
  • 4,067
  • 1
  • 31
  • 43
Tugrul Ates
  • 9,451
  • 2
  • 33
  • 59
13

For example

import inspect
frame = inspect.currentframe()
# __FILE__
fileName  =  frame.f_code.co_filename
# __LINE__
fileNo = frame.f_lineno

There's more here http://docs.python.org/library/inspect.html

ahuigo
  • 2,929
  • 2
  • 25
  • 45
Preet Sangha
  • 64,563
  • 18
  • 145
  • 216
12

Building on geowar's answer:

class __LINE__(object):
    import sys

    def __repr__(self):
        try:
            raise Exception
        except:
            return str(sys.exc_info()[2].tb_frame.f_back.f_lineno)

__LINE__ = __LINE__()

If you normally want to use __LINE__ in e.g. print (or any other time an implicit str() or repr() is taken), the above will allow you to omit the ()s.

(Obvious extension to add a __call__ left as an exercise to the reader.)

Matthew
  • 2,593
  • 22
  • 25
  • Why pack the `return` statement in a trivial (read: always on) try-raise-except triplet? – Whaa Sep 06 '21 at 12:28
  • @Whaa, as opposed to what? The `return` *inspects the exception* I just raised, as a method of obtaining the stack. Presumably that isn't the only way, but at least Tugrul Ates seems (slightly) more complicated and requires a less-used `import`. – Matthew Sep 06 '21 at 14:06
  • Understood. I missed the use of Python's silly implicit exception information mechanism. – Whaa Sep 09 '21 at 05:47
11

You can refer my answer: https://stackoverflow.com/a/45973480/1591700

import sys
print sys._getframe().f_lineno

You can also make lambda function

Mohammad Shahid Siddiqui
  • 3,730
  • 2
  • 27
  • 12
7

I was also interested in a __LINE__ command in python. My starting point was https://stackoverflow.com/a/6811020 and I extended it with a metaclass object. With this modification it has the same behavior like in C++.

import inspect

class Meta(type):
    def __repr__(self):
        # Inspiration: https://stackoverflow.com/a/6811020
        callerframerecord = inspect.stack()[1]  # 0 represents this line
        # 1 represents line at caller
        frame = callerframerecord[0]
        info = inspect.getframeinfo(frame)
        # print(info.filename)  # __FILE__     -> Test.py
        # print(info.function)  # __FUNCTION__ -> Main
        # print(info.lineno)  # __LINE__     -> 13
        return str(info.lineno)

class __LINE__(metaclass=Meta):
    pass

print(__LINE__)  # print for example 18
7

wow, 7 year old question :)

Anyway, taking Tugrul's answer, and writing it as a debug type method, it can look something like:

def debug(message):
    import sys
    import inspect
    callerframerecord = inspect.stack()[1]
    frame = callerframerecord[0]
    info = inspect.getframeinfo(frame)
    print(info.filename, 'func=%s' % info.function, 'line=%s:' % info.lineno, message)

def somefunc():
    debug('inside some func')

debug('this')
debug('is a')
debug('test message')
somefunc()

Output:

/tmp/test2.py func=<module> line=12: this
/tmp/test2.py func=<module> line=13: is a
/tmp/test2.py func=<module> line=14: test message
/tmp/test2.py func=somefunc line=10: inside some func
Hugh Perkins
  • 7,975
  • 7
  • 63
  • 71
4
import inspect
    .
    .
    .
def __LINE__():
    try:
        raise Exception
    except:
        return sys.exc_info()[2].tb_frame.f_back.f_lineno

def __FILE__():
    return inspect.currentframe().f_code.co_filename
    .
    .
    .
print "file: '%s', line: %d" % (__FILE__(), __LINE__())
geowar
  • 4,397
  • 1
  • 28
  • 24
3

Here is a tool to answer this old yet new question! I recommend using icecream!

Do you ever use print() or log() to debug your code? Of course, you do. IceCream, or ic for short, makes print debugging a little sweeter.

ic() is like print(), but better:

  1. It prints both expressions/variable names and their values.
  2. It's 40% faster to type.
  3. Data structures are pretty printed.
  4. Output is syntax highlighted.
  5. It optionally includes program context: filename, line number, and parent function.

For example, I created a module icecream_test.py, and put the following code inside it.

from icecream import ic
ic.configureOutput(includeContext=True)
def foo(i):
    return i + 333

ic(foo(123))

Prints

ic| icecream_test.py:6 in <module>- foo(123): 456
abdullah.cu
  • 674
  • 6
  • 11
0

To get the line number in Python without importing the whole sys module...

First import the _getframe submodule:

from sys import _getframe

Then call the _getframe function and use its' f_lineno property whenever you want to know the line number:

print(_getframe().f_lineno)  # prints the line number

From the interpreter:

>>> from sys import _getframe
... _getframe().f_lineno  # 2

Word of caution from the official Python Docs:

CPython implementation detail: This function should be used for internal and specialized purposes only. It is not guaranteed to exist in all implementations of Python.

In other words: Only use this code for personal testing / debugging reasons.

See the Official Python Documentation on sys._getframe for more information on the sys module, and the _getframe() function / submodule.

Based on Mohammad Shahid's answer (above).

Elliot G.
  • 88
  • 2
  • 7
0
import inspect
frame = inspect.currentframe()
print(f"{frame.f_lineno}\tdebugtext")
l = lambda: frame.f_lineno
print(f"{l()}\tdebugtext")

This prints:

3   debugtext
5   debugtext
Peter-dM
  • 9
  • 1