67

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?

3
  • 3
    You always print error log like that? That's remarkable, since there is no print function in C++. Commented Jul 25, 2011 at 1:35
  • 1
    @Tomalak typo, in python thread now. :) Commented Jul 25, 2011 at 1:39
  • 1
    Once you go Python, you never go back (much). Commented Jul 25, 2011 at 3:34

11 Answers 11

96

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__ -> 14 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__) 
Sign up to request clarification or add additional context in comments.

Comments

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

1 Comment

And a simple way to get fileNo: fileNo = frame.f_lineno
13

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

import sys print sys._getframe().f_lineno 

You can also make lambda function

Comments

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.)

3 Comments

Why pack the return statement in a trivial (read: always on) try-raise-except triplet?
@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.
Understood. I missed the use of Python's silly implicit exception information mechanism.
8

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 

Comments

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 

Comments

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__()) 

Comments

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 

Comments

1

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).

Comments

1
def get_frameinfo(framelvl=1): """ return info about the caller line, eg: ``` def my_fn(): print(get_frameinfo()) my_fn() ``` would print something like `{'file': '/tmp/ipykernel_93217/1851559004.py', 'fn': 'my_fn', 'line': 2}` """ f = sys._getframe(framelvl) return dict(file=f.f_code.co_filename, fn=f.f_code.co_name, line=f.f_lineno) 

i think this one is ideal, as you can easily control which frame it reads, and decide what to do with the output

Comments

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 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.