Is there a way to programatically get the line number and name of a function?
For example, I want to pass a list of strings to a function :
s = [calling_module, calling_function, line_number]
report(s)
Currently I just put it all in manually :
s = ["module abc", "func()", "line 22", "notes"]
report(s)
But I would like to know if there is an automatic way for python to fill in the module name (I think __name__ does that), function name and line number for me. Is there a way?
Use inspect module functions. For example,
import inspect
def b():
f = inspect.currentframe()
current = inspect.getframeinfo(f)
caller = inspect.getframeinfo(f.f_back)
#caller = inspect.getframeinfo(inspect.getouterframes(f)[1][0])
print(__name__, current.filename, current.function, current.lineno, caller.function)
def a():
b()
a()
You may want something along the lines of traceback.extract_stack():
>>> def test():
... print "In Function"
... print traceback.extract_stack()
...
>>>
>>> test()
In Function
[('<stdin>', 1, '<module>', None), ('<stdin>', 3, 'test', None)]
Though the results would need to be parsed.
from inspect import currentframe, getframeinfo, getmodulename
def report():
f = getframeinfo(currentframe().f_back)
print getmodulename(f.filename), f.lineno, f.function
Note that using
__name__
will return the name of the module containing report, while the code above will show the name of the module that called report.
Related
Is there a library for interpreting python code within a python program?
Sample usage might look like this..
code = """
def hello():
return 'hello'
hello()
"""
output = Interpreter.run(code)
print(output)
which then outputs
hello
found this example from grepper
the_code = '''
a = 1
b = 2
return_me = a + b
'''
loc = {}
exec(the_code, globals(), loc)
return_workaround = loc['return_me']
print(return_workaround)
apparently you can pass global and local scope into exec. In your use case, you would just use a named variable instead of returning.
You can use the exec function. You can't get the return value from the code variable. Instead you can print it there itself.
code = """
def hello():
print('hello')
hello()
"""
exec(code)
I want to get information about the callers of a specific function in python. For example:
class SomeClass():
def __init__(self, x):
self.x = x
def caller(self):
return special_func(self.x)
def special_func(x):
print "My caller is the 'caller' function in an 'SomeClass' class."
Is it possible with python?
Yes, the sys._getframe() function let's you retrieve frames from the current execution stack, which you can then inspect with the methods and documentation found in the inspect module; you'll be looking for specific locals in the f_locals attribute, as well as for the f_code information:
import sys
def special_func(x):
callingframe = sys._getframe(1)
print 'My caller is the %r function in a %r class' % (
callingframe.f_code.co_name,
callingframe.f_locals['self'].__class__.__name__)
Note that you'll need to take some care to detect what kind of information you find in each frame.
sys._getframe() returns a frame object, you can chain through the whole stack by following the f_back reference on each. Or you can use the inspect.stack() function to produce a lists of frames with additional information.
An example:
def f1(a):
import inspect
print 'I am f1 and was called by', inspect.currentframe().f_back.f_code.co_name
return a
def f2(a):
return f1(a)
Will retrieve the "immediate" caller.
>>> f2(1)
I am f1 and was called by f2
And if wasn't called from another you get (in IDLE):
>>> f1(1)
I am f1 and was called by <module>
Thanks to Jon Clements answer I was able to make a function that returns an ordered list of all callers:
def f1():
names = []
frame = inspect.currentframe()
## Keep moving to next outer frame
while True:
try:
frame = frame.f_back
name = frame.f_code.co_name
names.append(name)
except:
break
return names
and when called in a chain:
def f2():
return f1()
def f3():
return f2()
def f4():
return f3()
print f4()
looks like this:
['f2', 'f3', 'f4', '<module>']
In my case I filter out anything at '<module>' and after, and then take the last item to be the name of the originating caller.
Or modify the original loop to bail at the first appearance of any name starting with '<':
frame = frame.f_back
name = frame.f_code.co_name
if name[0] == '<':
break
names.append(name)
I am trying to get a list of functions from a module using inspect.getmembers in the order of source code.
Below is the code
def get_functions_from_module(app_module):
list_of_functions = dict(inspect.getmembers(app_module,
inspect.isfunction))
return list_of_functions.values
The current code will not return the list of function objects in order of the source code and I'm wondering if it would be possible to order it.
Thank you!
I think I came up with a solution.
def get_line_number_of_function(func):
return func.__code__.co_firstlineno
def get_functions_from_module(app_module):
list_of_functions = dict(inspect.getmembers(app_module,
inspect.isfunction))
return sorted(list_of_functions.values(), key=lambda x:
get_line_number_of_function(x))
You can sort by line numbers using inspect.findsource. Docstring from the source code of that function:
def findsource(object):
"""Return the entire source file and starting line number for an object.
The argument may be a module, class, method, function, traceback, frame,
or code object. The source code is returned as a list of all the lines
in the file and the line number indexes a line in that list. An OSError
is raised if the source code cannot be retrieved."""
Here's an example in Python 2.7:
import ab.bc.de.t1 as t1
import inspect
def get_functions_from_module(app_module):
list_of_functions = inspect.getmembers(app_module, inspect.isfunction)
return list_of_functions
fns = get_functions_from_module(t1)
def sort_by_line_no(fn):
fn_name, fn_obj = fn
source, line_no = inspect.findsource(fn_obj)
return line_no
for name, fn in sorted(fns, key=sort_by_line_no):
print name, fn
My ab.bc.de.t1 is defined as follows:
class B(object):
def a():
print 'test'
def c():
print 'c'
def a():
print 'a'
def b():
print 'b'
And the output I get when I try retrieving sorted functions is below:
c <function c at 0x00000000362517B8>
a <function a at 0x0000000036251438>
b <function b at 0x0000000036251668>
>>>
Python: How to get the caller's method name in the called method?
Assume I have 2 methods:
def method1(self):
...
a = A.method2()
def method2(self):
...
If I don't want to do any change for method1, how to get the name of the caller (in this example, the name is method1) in method2?
inspect.getframeinfo and other related functions in inspect can help:
>>> import inspect
>>> def f1(): f2()
...
>>> def f2():
... curframe = inspect.currentframe()
... calframe = inspect.getouterframes(curframe, 2)
... print('caller name:', calframe[1][3])
...
>>> f1()
caller name: f1
this introspection is intended to help debugging and development; it's not advisable to rely on it for production-functionality purposes.
Shorter version:
import inspect
def f1(): f2()
def f2():
print 'caller name:', inspect.stack()[1][3]
f1()
(with thanks to #Alex, and Stefaan Lippen)
This seems to work just fine:
import sys
print sys._getframe().f_back.f_code.co_name
I would use inspect.currentframe().f_back.f_code.co_name. Its use hasn't been covered in any of the prior answers which are mainly of one of three types:
Some prior answers use inspect.stack but it's known to be too slow.
Some prior answers use sys._getframe which is an internal private function given its leading underscore, and so its use is implicitly discouraged.
One prior answer uses inspect.getouterframes(inspect.currentframe(), 2)[1][3] but it's entirely unclear what [1][3] is accessing.
import inspect
from types import FrameType
from typing import cast
def demo_the_caller_name() -> str:
"""Return the calling function's name."""
# Ref: https://stackoverflow.com/a/57712700/
return cast(FrameType, cast(FrameType, inspect.currentframe()).f_back).f_code.co_name
if __name__ == '__main__':
def _test_caller_name() -> None:
assert demo_the_caller_name() == '_test_caller_name'
_test_caller_name()
Note that cast(FrameType, frame) is used to satisfy mypy.
Acknowlegement: comment by 1313e for an answer.
I've come up with a slightly longer version that tries to build a full method name including module and class.
https://gist.github.com/2151727 (rev 9cccbf)
# Public Domain, i.e. feel free to copy/paste
# Considered a hack in Python 2
import inspect
def caller_name(skip=2):
"""Get a name of a caller in the format module.class.method
`skip` specifies how many levels of stack to skip while getting caller
name. skip=1 means "who calls me", skip=2 "who calls my caller" etc.
An empty string is returned if skipped levels exceed stack height
"""
stack = inspect.stack()
start = 0 + skip
if len(stack) < start + 1:
return ''
parentframe = stack[start][0]
name = []
module = inspect.getmodule(parentframe)
# `modname` can be None when frame is executed directly in console
# TODO(techtonik): consider using __main__
if module:
name.append(module.__name__)
# detect classname
if 'self' in parentframe.f_locals:
# I don't know any way to detect call from the object method
# XXX: there seems to be no way to detect static method call - it will
# be just a function call
name.append(parentframe.f_locals['self'].__class__.__name__)
codename = parentframe.f_code.co_name
if codename != '<module>': # top level usually
name.append( codename ) # function or a method
## Avoid circular refs and frame leaks
# https://docs.python.org/2.7/library/inspect.html#the-interpreter-stack
del parentframe, stack
return ".".join(name)
Bit of an amalgamation of the stuff above. But here's my crack at it.
def print_caller_name(stack_size=3):
def wrapper(fn):
def inner(*args, **kwargs):
import inspect
stack = inspect.stack()
modules = [(index, inspect.getmodule(stack[index][0]))
for index in reversed(range(1, stack_size))]
module_name_lengths = [len(module.__name__)
for _, module in modules]
s = '{index:>5} : {module:^%i} : {name}' % (max(module_name_lengths) + 4)
callers = ['',
s.format(index='level', module='module', name='name'),
'-' * 50]
for index, module in modules:
callers.append(s.format(index=index,
module=module.__name__,
name=stack[index][3]))
callers.append(s.format(index=0,
module=fn.__module__,
name=fn.__name__))
callers.append('')
print('\n'.join(callers))
fn(*args, **kwargs)
return inner
return wrapper
Use:
#print_caller_name(4)
def foo():
return 'foobar'
def bar():
return foo()
def baz():
return bar()
def fizz():
return baz()
fizz()
output is
level : module : name
--------------------------------------------------
3 : None : fizz
2 : None : baz
1 : None : bar
0 : __main__ : foo
You can use decorators, and do not have to use stacktrace
If you want to decorate a method inside a class
import functools
# outside ur class
def printOuterFunctionName(func):
#functools.wraps(func)
def wrapper(self):
print(f'Function Name is: {func.__name__}')
func(self)
return wrapper
class A:
#printOuterFunctionName
def foo():
pass
you may remove functools, self if it is procedural
An alternative to sys._getframe() is used by Python's Logging library to find caller information. Here's the idea:
raise an Exception
immediately catch it in an Except clause
use sys.exc_info to get Traceback frame (tb_frame).
from tb_frame get last caller's frame using f_back.
from last caller's frame get the code object that was being executed in that frame.
In our sample code it would be method1 (not method2) being executed.
From code object obtained, get the object's name -- this is caller method's name in our sample.
Here's the sample code to solve example in the question:
def method1():
method2()
def method2():
try:
raise Exception
except Exception:
frame = sys.exc_info()[2].tb_frame.f_back
print("method2 invoked by: ", frame.f_code.co_name)
# Invoking method1
method1()
Output:
method2 invoked by: method1
Frame has all sorts of details, including line number, file name, argument counts, argument type and so on. The solution works across classes and modules too.
Code:
#!/usr/bin/env python
import inspect
called=lambda: inspect.stack()[1][3]
def caller1():
print "inside: ",called()
def caller2():
print "inside: ",called()
if __name__=='__main__':
caller1()
caller2()
Output:
shahid#shahid-VirtualBox:~/Documents$ python test_func.py
inside: caller1
inside: caller2
shahid#shahid-VirtualBox:~/Documents$
I found a way if you're going across classes and want the class the method belongs to AND the method. It takes a bit of extraction work but it makes its point. This works in Python 2.7.13.
import inspect, os
class ClassOne:
def method1(self):
classtwoObj.method2()
class ClassTwo:
def method2(self):
curframe = inspect.currentframe()
calframe = inspect.getouterframes(curframe, 4)
print '\nI was called from', calframe[1][3], \
'in', calframe[1][4][0][6: -2]
# create objects to access class methods
classoneObj = ClassOne()
classtwoObj = ClassTwo()
# start the program
os.system('cls')
classoneObj.method1()
Hey mate I once made 3 methods without plugins for my app and maybe that can help you, It worked for me so maybe gonna work for you too.
def method_1(a=""):
if a == "method_2":
print("method_2")
if a == "method_3":
print("method_3")
def method_2():
method_1("method_2")
def method_3():
method_1("method_3")
method_2()
I want to get information about the callers of a specific function in python. For example:
class SomeClass():
def __init__(self, x):
self.x = x
def caller(self):
return special_func(self.x)
def special_func(x):
print "My caller is the 'caller' function in an 'SomeClass' class."
Is it possible with python?
Yes, the sys._getframe() function let's you retrieve frames from the current execution stack, which you can then inspect with the methods and documentation found in the inspect module; you'll be looking for specific locals in the f_locals attribute, as well as for the f_code information:
import sys
def special_func(x):
callingframe = sys._getframe(1)
print 'My caller is the %r function in a %r class' % (
callingframe.f_code.co_name,
callingframe.f_locals['self'].__class__.__name__)
Note that you'll need to take some care to detect what kind of information you find in each frame.
sys._getframe() returns a frame object, you can chain through the whole stack by following the f_back reference on each. Or you can use the inspect.stack() function to produce a lists of frames with additional information.
An example:
def f1(a):
import inspect
print 'I am f1 and was called by', inspect.currentframe().f_back.f_code.co_name
return a
def f2(a):
return f1(a)
Will retrieve the "immediate" caller.
>>> f2(1)
I am f1 and was called by f2
And if wasn't called from another you get (in IDLE):
>>> f1(1)
I am f1 and was called by <module>
Thanks to Jon Clements answer I was able to make a function that returns an ordered list of all callers:
def f1():
names = []
frame = inspect.currentframe()
## Keep moving to next outer frame
while True:
try:
frame = frame.f_back
name = frame.f_code.co_name
names.append(name)
except:
break
return names
and when called in a chain:
def f2():
return f1()
def f3():
return f2()
def f4():
return f3()
print f4()
looks like this:
['f2', 'f3', 'f4', '<module>']
In my case I filter out anything at '<module>' and after, and then take the last item to be the name of the originating caller.
Or modify the original loop to bail at the first appearance of any name starting with '<':
frame = frame.f_back
name = frame.f_code.co_name
if name[0] == '<':
break
names.append(name)