Generate function calls tree from multiple Python files

3.7k views Asked by At

I have inherited a bunch of Python files and looking for a way to get an understanding of what is going on within them by collecting information about all the functions that have been defined and called within those files.

Example of a file (MainModule.py):

Import module1
Import module2
Import module3
 
...
Def func1():
...
Def func2():
...
 
result1 = Module1.funcX(args)
result2 = Module2.funcY(args)
...

By looking into this file, I want IDE to report what functions have been defined within this file (this is something I can do with Wing IDE), but also what functions (that were defined within .py files located within the same folder or a project) were called. Obviosly, I don't want to report use of Python system functions (such as print(), etc.), but only those functions that were defined within files within my project (could be a folder, doesn't really matter).

So in this example, I'd like to get something like this: in file MainFunction.py functions funcX and funcY were called from Module1.py file and Module2.py file respectively. I will use this information to build a reference schema in Visio (or some other piece of software) which I will use while refactoring the code.

I am aware of using Find points of use and Goto definition within WingIDE, but reading through 20 files looking for functions would be too cumbersome.

I have used PyScripter and WingIDE Pro, but it seems as those IDEs lack this functionality. What IDE has support for this kind of operation? If none, is there any other straightforward way to achieve this?

2

There are 2 answers

1
Hugo On BEST ANSWER

Generating call graphs of dynamic languages through static analysis is practically impossible (even if an approximation is possible for simple examples). It is therefore typically done dynamically at run-time, through use of something like pycallgraph (https://pypi.python.org/pypi/pycallgraph).

Good unit test coverage of the Python code is therefore of paramount importance. If unit tests are lacking, improving unit test coverage is likely a very valuable step prior to tackling refactoring.

Here is a previous StackOverflow question that also touches on this: Build a Call graph in python including modules and functions?

0
Karol Zlot On

Currently original pycallgraph is not maintained anymore. I couldn't even install it when using Python 3.9.

But some forks were created, most recently active is CallGraph4Py:

On Windows remember to install Graphviz, it's necessary for image generation.

Example usage:

from pycallgraph import PyCallGraph
from pycallgraph.output import GraphvizOutput

def a1():
    print("a1")

def a2():
    print("a2")

def a3():
    a1()
    print("a3")

def a4():
    a3()
    a2()
    print("a4")

with PyCallGraph(output=GraphvizOutput()):
    a4()

Remember that you need to run it without debugger (in vscode Ctrl+F5).

It generates image with None filename in project folder, it is necessary to add .png extension to view it.

Generated image:

Generated image