Reputation: 25376
Let's say we have two python files (say, file_1.py
and file_2.py
), with the following structure:
-- file_1.py
# file_1.py imports file_2
fo(x) # a function
A # a class
fun(y) # some method
_bo(y) # some "hidden" method
-- file2.py
bar(x) # a function
I would like some function like get_functions_and_methods('file_1.py')
with an output like this:
'fo(x)', 'a.fun(y)', 'a._bo(y)'
Given that I'm a novice in Python, I have no idea how to go about constructing such information, and would be happy for help.
The closest I found online was:
__import__
(from here: Import file using string as name), it didn't seem to work. The issue is that I don't just want to capture all of the def, but also connect them to classes if they are embedded within them.How should I go about solving this? Thanks!
Upvotes: 2
Views: 1073
Reputation: 7799
Say you have a python file with following members
file1.py
def fo(x):
pass
class A:
def fun(self, y):
pass
def _bo(self, y):
pass
def NS(y, z):
pass
class B:
def foo(self, z):
pass
def _bar(self, t):
pass
Expected output would be :
fo(x), A.fun(self, y), A._bo(self, y), A.NS(y, z), B.foo(self, z), B._bar(self, t)
We can use ast
module of python to read the python file and its members in its respective format.
import ast
with open(filepath) as file:
node = ast.parse(file.read())
result = []
functions = [n for n in node.body if isinstance(n, ast.FunctionDef)]
classes = [n for n in node.body if isinstance(n, ast.ClassDef)]
def show_info(functionNode):
function_rep = ''
function_rep = functionNode.name + '('
for arg in functionNode.args.args:
function_rep += arg.arg + ','
function_rep = function_rep.rstrip(function_rep[-1])
function_rep += ')'
return function_rep
for function in functions:
result.append(show_info(function))
for class_ in classes:
methods = [n for n in class_.body if isinstance(n, ast.FunctionDef)]
for method in methods:
result.append((class_.name + '.' + show_info(method)))
print(', '.join(result))
This gives us the expected result
fo(x), A.fun(self,y), A._bo(self,y), A.NS(y,z), B.foo(self,z), B._bar(self,t)
To run everything at once, just change the filepath in the code below
import ast
with open(r'YOURPYTHONFILEPATH') as file:
node = ast.parse(file.read())
def show_info(functionNode):
function_rep = ''
function_rep = functionNode.name + '('
for arg in functionNode.args.args:
function_rep += arg.arg + ','
function_rep = function_rep.rstrip(function_rep[-1])
function_rep += ')'
return function_rep
result = []
functions = [n for n in node.body if isinstance(n, ast.FunctionDef)]
classes = [n for n in node.body if isinstance(n, ast.ClassDef)]
for function in functions:
result.append(show_info(function))
for class_ in classes:
methods = [n for n in class_.body if isinstance(n, ast.FunctionDef)]
for method in methods:
result.append((class_.name + '.' + show_info(method)))
print(', '.join(result))
# This prints expected output
# fo(x), A.fun(self,y), A._bo(self,y), A.NS(y,z), B.foo(self,z), B._bar(self,t)
Upvotes: 7