Reputation: 198
what I want to do...
I have a module called 'my_library.py' which contains some functions or methods.
I have another module called 'test_library.py' and from test_library I want to print source code of some specific functions which is inside "my_library" module
I know we can do it using....
print(inspect.getsource(my_library.add))
or
print(open(my_library.__file__).read())
here, i want to take the function or module name from the user as an input
example :
**my_library.py**
def add(x,y):
return x+y
def substract(x,y):
return x-y
**test_library.py**
import inspect
import my_library
name = "my_library.substract"
print(inspect.getsource(name))
TypeError: module, class, method, function, traceback, frame, or code object was expected, got str
I have tried to convert that string input into object, file, class ...nothing seems to work
is there any way to take the input from a user and show that specific function or module?
any suggestions or advice to solve the problem?
thanks in advance
Upvotes: 2
Views: 832
Reputation: 1319
Say we had a file module.py
:
def test_func(arg1, arg2):
return arg1 + arg2
We can resolve this member for use by getsource()
from another region of code by getting a reference to the function object:
import inspect
import sys
import module
def main():
# what the user would input
input_str = 'module.test_func'
# split user input up into individual members
name_list = input_str.split('.')
# extract the starting point name
base_name = name_list[0]
# check to make sure that name exists in the current scope and extract a reference to it
if base_name in locals():
base_obj = locals()[base_name]
elif base_name in globals():
base_obj = globals()[base_name]
else:
print('base name {} is unknown'.format(base_name))
return 1
# iteratively step through the attribute chain
containing_object = base_obj
for name in name_list[1:]:
try:
containing_object = getattr(containing_object, name)
except AttributeError:
print('unable to resolve name {} from object {}'.format(name, containing_object))
return 1
# print out source of final reference
print(inspect.getsource(containing_object))
return 0
if __name__ == '__main__':
sys.exit(main())
You could also extend this to retrieve members of modules that haven't yet been imported using importlib
Upvotes: 1
Reputation: 28370
You need to create an actual object to pass to get_source
, e.g.:
In [1]: def add(x,y):
...: return x+y
...:
In [2]: def substract(x,y): return x-y
In [3]: %save my_library.py 1-2
The following commands were written to file `my_library.py`:
def add(x,y):
return x+y
def substract(x,y): return x-y
In [4]: import inspect
In [5]: import my_library
In [6]: obj = my_library.substract
In [7]: inspect.getsource(obj)
Out[7]: 'def substract(x,y): return x-y\n'
In [8]: obj = my_library.add
In [9]: inspect.getsource(obj)
Out[9]: 'def add(x,y):\n return x+y\n'
In [10]:
You can generate them from strings by using eval
on the strings, e.g.:
for item in dir(my_library):
if not item.startswith('_'):
print(item)
nam = '.'.join(['my_library', item])
print(inspect.getsource(eval(nam)))
Gives:
add
def add(x,y):
return x+y
substract
def substract(x,y): return x-y
Upvotes: 1