pycallgraph is a Python module that creates call graphs for Python programs.

No Maintenance Intended

Project Abandoned

Many apologies. I've stopped maintaining this project due to personal time constraints. Blog post with more information.

I'm happy to forward users to any new forks, or to discuss PyPI ownership.

Python Call Graph

Welcome! Python Call Graph is a Python module that creates call graph visualizations for Python applications.

Screenshots

Click on the images below to see a larger version and the source code that generated them.

https://pycallgraph.readthedocs.io/en/develop/_images/basic_thumb.png https://pycallgraph.readthedocs.io/en/develop/_images/regexp_grouped_thumb.png https://pycallgraph.readthedocs.io/en/develop/_images/regexp_ungrouped_thumb.png

Project Status

The latest version is 1.0.1 which was released on 2013-09-17, and is a backwards incompatible from the previous release.

The project lives on GitHub, where you can report issues, contribute to the project by forking the project then creating a pull request, or just browse the source code.

The documentation needs some work stiil. Feel free to contribute :)

Features

  • Support for Python 2.7+ and Python 3.3+.
  • Static visualizations of the call graph using various tools such as Graphviz and Gephi.
  • Execute pycallgraph from the command line or import it in your code.
  • Customisable colors. You can programatically set the colors based on number of calls, time taken, memory usage, etc.
  • Modules can be visually grouped together.
  • Easily extendable to create your own output formats.

Quick Start

Installation is easy as:

pip install pycallgraph

You can either use the command-line interface for a quick visualization of your Python script, or the pycallgraph module for more fine-grained settings.

The following examples specify graphviz as the outputter, so it's required to be installed. They will generate a file called pycallgraph.png.

The command-line method of running pycallgraph is:

$ pycallgraph graphviz -- ./mypythonscript.py

A simple use of the API is:

from pycallgraph import PyCallGraph
from pycallgraph.output import GraphvizOutput

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

Documentation

Feel free to browse the documentation of pycallgraph for the usage guide and API reference.

Comments
  • Add first decorator

    Add first decorator

    fix #120 port from https://github.com/ivannotes/pycallgraph/commit/0b2fb090a6dd2664235600af149f390cdabc3b00 by @ivannotes

    rename decorator to trace

    usage example:

    import pycallgraph
    from pycallgraph.output import GraphvizOutput
    
    @pycallgraph.decorators.trace(output=GraphvizOutput())
    def yours_very_slow_function():
        ....
    
    

    TODO: docs

  • Track call order

    Track call order

    It would be good to be able to see the order in which functions were called. This could get out of hand quite quickly, so maybe track only the first calls.

  • Track call order

    Track call order

    It would be good to be able to see the order in which functions were called. This could get out of hand quite quickly, so maybe track only the first calls.

  • Track call order

    Track call order

    It would be good to be able to see the order in which functions were called. This could get out of hand quite quickly, so maybe track only the first calls.

  • Track call order

    Track call order

    It would be good to be able to see the order in which functions were called. This could get out of hand quite quickly, so maybe track only the first calls.

  • pip install fails in python3

    pip install fails in python3

    It looks like pycallgraph/output/gephi.py is using python 2.x style syntax:

    Downloading/unpacking pycallgraph (from -r requirements/dev.txt (line 9))
      Downloading pycallgraph-1.0.1.tar.gz
      Running setup.py egg_info for package pycallgraph
        Traceback (most recent call last):
          File "<string>", line 16, in <module>
          File "/projects/acme_project/virtualenv/acme/build/pycallgraph/setup.py", line 9, in <module>
            import pycallgraph
          File "pycallgraph/__init__.py", line 15, in <module>
            from .pycallgraph import PyCallGraph
          File "pycallgraph/pycallgraph.py", line 3, in <module>
            from .output import Output
          File "pycallgraph/output/__init__.py", line 5, in <module>
            from .gephi import GephiOutput
          File "pycallgraph/output/gephi.py", line 28
            return u'\n'.join([
                       ^
        SyntaxError: invalid syntax
        Complete output from command python setup.py egg_info:
        Traceback (most recent call last):
    
      File "<string>", line 16, in <module>
    
      File "/projects/acme_project/virtualenv/acme/build/pycallgraph/setup.py", line 9, in <module>
    
        import pycallgraph
    
      File "pycallgraph/__init__.py", line 15, in <module>
    
        from .pycallgraph import PyCallGraph
    
      File "pycallgraph/pycallgraph.py", line 3, in <module>
    
        from .output import Output
    
      File "pycallgraph/output/__init__.py", line 5, in <module>
    
        from .gephi import GephiOutput
    
      File "pycallgraph/output/gephi.py", line 28
    
        return u'\n'.join([
    
                   ^
    
    SyntaxError: invalid syntax
    
  • Allow command line options to called scripts

    Allow command line options to called scripts

    I was amazed at how simple it was to install and use pycallgraph. Just one suggestion.

    It would be very helpful if you could specify sys.argv to the called script on the command line. That way I wouldn't have to make a new script file for every set of options. If you put the output filename before the scriptfile you could feed the rest of the command line to the called script. For example:

    {{{ pycallgraph-dot.py test1.png myscript.py --spam=42 ham.txt eggs.txt }}}

  • Allow command line options to called scripts

    Allow command line options to called scripts

    I was amazed at how simple it was to install and use pycallgraph. Just one suggestion.

    It would be very helpful if you could specify sys.argv to the called script on the command line. That way I wouldn't have to make a new script file for every set of options. If you put the output filename before the scriptfile you could feed the rest of the command line to the called script. For example:

    {{{ pycallgraph-dot.py test1.png myscript.py --spam=42 ham.txt eggs.txt }}}

  • Allow command line options to called scripts

    Allow command line options to called scripts

    I was amazed at how simple it was to install and use pycallgraph. Just one suggestion.

    It would be very helpful if you could specify sys.argv to the called script on the command line. That way I wouldn't have to make a new script file for every set of options. If you put the output filename before the scriptfile you could feed the rest of the command line to the called script. For example:

    {{{ pycallgraph-dot.py test1.png myscript.py --spam=42 ham.txt eggs.txt }}}

  • Allow command line options to called scripts

    Allow command line options to called scripts

    I was amazed at how simple it was to install and use pycallgraph. Just one suggestion.

    It would be very helpful if you could specify sys.argv to the called script on the command line. That way I wouldn't have to make a new script file for every set of options. If you put the output filename before the scriptfile you could feed the rest of the command line to the called script. For example:

    {{{ pycallgraph-dot.py test1.png myscript.py --spam=42 ham.txt eggs.txt }}}

  • Doesn't work with Django's SimpleLazyObject

    Doesn't work with Django's SimpleLazyObject

    I'm using pycallgraph 0.5.1, Django 1.3.1, Python 2.7.2 32bit.

    Line 235 of pycallgraph.py, which gets the "class" of "self" in the current call being traced, causes an infinite loop. The method being traced is SimpleLazyObject's "init", which among other things sets "self._wrapped". ".class" triggers the "__get_class" method on the object, which checks if "_wrapped" is None, but since the constructor hasn't run yet (it was intercepted by the tracer), this gets translated into a "getattr" call on the object, which again checks if "_wrapped" is None... etc.

    Here is the relevant part the stack trace. I used custom middleware to integrate pycallgraph in Django.

    C:\Python27\lib\site-packages\django\contrib\auth\context_processors.py in auth   57. 'user': SimpleLazyObject(get_user), C:\Python27\lib\site-packages\django\utils\functional.py in init   316. def init(self, func): C:\Python27\lib\site-packages\pycallgraph.py in tracer   235. class_name = frame.f_locals['self'].class.name C:\Python27\lib\site-packages\django\utils\functional.py in __get_class   354. if self._wrapped is None: self._setup() C:\Python27\lib\site-packages\django\utils\functional.py in getattr   275. if self._wrapped is None: ... (this is the infinite loop) ... C:\Python27\lib\site-packages\django\utils\functional.py in getattr   275. if self._wrapped is None:

  • test_no_stdlib and underlying functionality incorrect for distros

    test_no_stdlib and underlying functionality incorrect for distros

    Config.init_libpath only looks at sysconfig.get_python_lib() (usually /usr/lib/), and doesnt include sysconfig.get_python_lib(plat_specific=True) , which is usually /usr/lib64. The later is where re.match will come from for most distro users. Both directories need to be used to determine if a module is part of the stdlib.

  •  PyCallGraphException: The command

    PyCallGraphException: The command "dot -Tpng -oML4AR2 pycallgraph.png C:\Users\XXXX\AppData\Local\Temp\tmpxw3sbjz1" failed with error code 1.

    I have repeatedly tried PyCallGraphException with different results. I have gotten it to work with max_depth=4, but not max_depth=5. I do not appear to have a file named "tmpxw3sbjz1" (or similar file with a recent timestamp). Dot is in my path and I can execute the command manually from within Jupyter, but this command ("dot -Tpng -oML4AR2 pycallgraph.png C:\Users\XXXX\AppData\Local\Temp\tmpxw3sbjz1" ) does not work.

    Here is the code

        from pycallgraph import PyCallGraph
        from pycallgraph import Config
        from pycallgraph import GlobbingFilter
        from pycallgraph.output import GraphvizOutput
    
        pycall_exclude = ['time.*', 'datetime.*', 'dateutil.*', 'argparse.*',
                        'numpy.*', 'pandas.*', 'yaml.*', 'pickle.*',
                        'psutil.*', 'sys.*', 'warnings.*', 'sklearn.*', 
                        'collections.*', 'scipy.*', 'tqdm.*', 'os.*',
                        'logging.*', 'pycallgraph.*']
    
        config = Config(max_depth=5)
    
        config.trace_filter = GlobbingFilter(exclude=pycall_exclude)
        graphviz = GraphvizOutput(output_file='ML4AR2 pycallgraph.png')
    
        if __name__ == '__main__':
            with PyCallGraph(output=graphviz, config=config):
                   main()
    

    Here is a description of my environment

    INSTALLED VERSIONS
    ------------------
    commit: None
    python: 3.6.8.final.0
    python-bits: 64
    OS: Windows
    OS-release: 10
    machine: AMD64
    processor: Intel64 Family 6 Model 78 Stepping 3, GenuineIntel
    byteorder: little
    LC_ALL: en_US_UTF-8
    LANG: en_US.UTF-8
    LOCALE: English_United States.1252
    
    pandas: 0.24.1
    pytest: 4.2.0
    pip: 19.0.1
    setuptools: 40.7.3
    Cython: 0.29.4
    numpy: 1.15.4
    scipy: 1.2.0
    pyarrow: None
    xarray: None
    IPython: 7.2.0
    sphinx: 1.8.4
    patsy: 0.5.1
    dateutil: 2.7.5
    pytz: 2018.9
    blosc: None
    bottleneck: 1.2.1
    tables: 3.4.4
    numexpr: 2.6.9
    feather: None
    matplotlib: 3.0.2
    openpyxl: 2.5.14
    xlrd: 1.2.0
    xlwt: 1.3.0
    xlsxwriter: 1.1.2
    lxml.etree: 4.3.0
    bs4: 4.7.1
    html5lib: 1.0.1
    sqlalchemy: 1.2.17
    pymysql: None
    psycopg2: None
    jinja2: 2.10
    s3fs: None
    fastparquet: None
    pandas_gbq: None
    pandas_datareader: None
    gcsfs: None
    

    Please advise

  • pycallgraph displaying chronology

    pycallgraph displaying chronology

    Dears,

    I would like to know if using pycallgraph I can show the chronology of the call graph. I'm thinking that at current time there is no special ordering about the "boxes" positioning .

  • Forking pycallgraph

    Forking pycallgraph

    pycallgraph has been a useful resource for performance testing my projects, but the PyPi release is far behind. I forked pycallgraph, merged the develop branch, and released pycallgraph2 on PyPi today.

    I'll be actively maintaining and updating pycallgraph2 at on my fork if anyone would like to contribute. Namely, it needs stability updates + a wiki.

  • Use a format that does not depends on locale

    Use a format that does not depends on locale

    Using pycallgraph==1.0.1 with python 3.5.3 and locale ('fr_FR', 'UTF-8'), I got a tons of UTF-8 random errors that were somehow fixed by just changing the format from n to d.

A very minimalistic python module that lets you track the time your code snippets take to run.

Clock Keeper A very minimalistic python module that lets you track the time your code snippets take to run. This package is available on PyPI! Run the

Jan 19, 2022
Turn your Python and Javascript code into DOT flowcharts
Turn your Python and Javascript code into DOT flowcharts

Notes from 2017 This is an older project which I am no longer working on. It was built before ES6 existed and before Python 3 had much usage. While it

Jan 9, 2023
Inspects Python source files and provides information about type and location of classes, methods etc

prospector About Prospector is a tool to analyse Python code and output information about errors, potential problems, convention violations and comple

Dec 31, 2022
Find dead Python code

Vulture - Find dead code Vulture finds unused code in Python programs. This is useful for cleaning up and finding errors in large code bases. If you r

Jan 3, 2023
Code audit tool for python.

Pylama Code audit tool for Python and JavaScript. Pylama wraps these tools: pycodestyle (formerly pep8) © 2012-2013, Florent Xicluna; pydocstyle (form

Dec 29, 2022
The strictest and most opinionated python linter ever!
The strictest and most opinionated python linter ever!

wemake-python-styleguide Welcome to the strictest and most opinionated python linter ever. wemake-python-styleguide is actually a flake8 plugin with s

Jan 5, 2023
The uncompromising Python code formatter
The uncompromising Python code formatter

The Uncompromising Code Formatter “Any color you like.” Black is the uncompromising Python code formatter. By using it, you agree to cede control over

Dec 28, 2022
A Python utility / library to sort imports.
A Python utility / library to sort imports.

Read Latest Documentation - Browse GitHub Code Repository isort your imports, so you don't have to. isort is a Python utility / library to sort import

Jan 6, 2023
A formatter for Python files

YAPF Introduction Most of the current formatters for Python --- e.g., autopep8, and pep8ify --- are made to remove lint errors from code. This has som

Dec 31, 2022
Performant type-checking for python.
Performant type-checking for python.

Pyre is a performant type checker for Python compliant with PEP 484. Pyre can analyze codebases with millions of lines of code incrementally – providi

Jan 7, 2023
Collection of library stubs for Python, with static types

typeshed About Typeshed contains external type annotations for the Python standard library and Python builtins, as well as third party packages as con

Jan 2, 2023
A system for Python that generates static type annotations by collecting runtime types

MonkeyType MonkeyType collects runtime types of function arguments and return values, and can automatically generate stub files or even add draft type

Jan 2, 2023
A static type analyzer for Python code

pytype - ? ✔ Pytype checks and infers types for your Python code - without requiring type annotations. Pytype can: Lint plain Python code, flagging c

Dec 31, 2022
Optional static typing for Python 3 and 2 (PEP 484)

Mypy: Optional Static Typing for Python Got a question? Join us on Gitter! We don't have a mailing list; but we are always happy to answer questions o

Jan 5, 2023
Static type checker for Python
Static type checker for Python

Static type checker for Python Speed Pyright is a fast type checker meant for large Python source bases. It can run in a “watch” mode and performs fas

Jan 7, 2023
A static analysis tool for Python

pyanalyze Pyanalyze is a tool for programmatically detecting common mistakes in Python code, such as references to undefined variables and some catego

Jan 7, 2023
Unbearably fast O(1) runtime type-checking in pure Python.
Unbearably fast O(1) runtime type-checking in pure Python.

Look for the bare necessities, the simple bare necessities. Forget about your worries and your strife. — The Jungle Book.

Dec 29, 2022
Typing-toolbox for Python 3 _and_ 2.7 w.r.t. PEP 484.
Typing-toolbox for Python 3 _and_ 2.7 w.r.t. PEP 484.

Welcome to the pytypes project pytypes is a typing toolbox w.r.t. PEP 484 (PEP 526 on the road map, later also 544 if it gets accepted). Its main feat

Dec 29, 2022
Data parsing and validation using Python type hints

pydantic Data validation and settings management using Python type hinting. Fast and extensible, pydantic plays nicely with your linters/IDE/brain. De

Jan 5, 2023