Skip to content
Branch: master
Find file History
Olshansk and miss-islington bpo-37958: Adding get_profile_dict to pstats (GH-15495)
pstats is really useful or profiling and printing the output of the execution of some block of code, but I've found on multiple occasions when I'd like to access this output directly in an easily usable dictionary on which I can further analyze or manipulate.

The proposal is to add a function called get_profile_dict inside of pstats that'll automatically return this data the data in an easily accessible dict.

The output of the following script:

```
import cProfile, pstats
import pprint
from pstats import func_std_string, f8

def fib(n):
    if n == 0:
        return 0
    if n == 1:
        return 1
    return fib(n-1) + fib(n-2)

pr = cProfile.Profile()
pr.enable()
fib(5)
pr.create_stats()

ps = pstats.Stats(pr).sort_stats('tottime', 'cumtime')

def get_profile_dict(self, keys_filter=None):
    """
        Returns a dict where the key is a function name and the value is a dict
        with the following keys:
            - ncalls
            - tottime
            - percall_tottime
            - cumtime
            - percall_cumtime
            - file_name
            - line_number

        keys_filter can be optionally set to limit the key-value pairs in the
        retrieved dict.
    """
    pstats_dict = {}
    func_list = self.fcn_list[:] if self.fcn_list else list(self.stats.keys())

    if not func_list:
        return pstats_dict

    pstats_dict["total_tt"] = float(f8(self.total_tt))
    for func in func_list:
        cc, nc, tt, ct, callers = self.stats[func]
        file, line, func_name = func
        ncalls = str(nc) if nc == cc else (str(nc) + '/' + str(cc))
        tottime = float(f8(tt))
        percall_tottime = -1 if nc == 0 else float(f8(tt/nc))
        cumtime = float(f8(ct))
        percall_cumtime = -1 if cc == 0 else float(f8(ct/cc))
        func_dict = {
            "ncalls": ncalls,
            "tottime": tottime, # time spent in this function alone
            "percall_tottime": percall_tottime,
            "cumtime": cumtime, # time spent in the function plus all functions that this function called,
            "percall_cumtime": percall_cumtime,
            "file_name": file,
            "line_number": line
        }
        func_dict_filtered = func_dict if not keys_filter else { key: func_dict[key] for key in keys_filter }
        pstats_dict[func_name] = func_dict_filtered

    return pstats_dict

pp = pprint.PrettyPrinter(depth=6)
pp.pprint(get_profile_dict(ps))
```

will produce:

```
{"<method 'disable' of '_lsprof.Profiler' objects>": {'cumtime': 0.0,
                                                      'file_name': '~',
                                                      'line_number': 0,
                                                      'ncalls': '1',
                                                      'percall_cumtime': 0.0,
                                                      'percall_tottime': 0.0,
                                                      'tottime': 0.0},
 'create_stats': {'cumtime': 0.0,
                  'file_name': '/usr/local/Cellar/python/3.7.4/Frameworks/Python.framework/Versions/3.7/lib/python3.7/cProfile.py',
                  'line_number': 50,
                  'ncalls': '1',
                  'percall_cumtime': 0.0,
                  'percall_tottime': 0.0,
                  'tottime': 0.0},
 'fib': {'cumtime': 0.0,
         'file_name': 'get_profile_dict.py',
         'line_number': 5,
         'ncalls': '15/1',
         'percall_cumtime': 0.0,
         'percall_tottime': 0.0,
         'tottime': 0.0},
 'total_tt': 0.0}
 ```

 As an example, this can be used to generate a stacked column chart using various visualization tools which will assist in easily identifying program bottlenecks.



https://bugs.python.org/issue37958



Automerge-Triggered-By: @gpshead
Latest commit 01602ae Jan 15, 2020
Permalink
Type Name Latest commit message Commit time
..
Failed to load latest commit information.
NEWS.d bpo-37958: Adding get_profile_dict to pstats (GH-15495) Jan 15, 2020
ACKS bpo-39048: Look up __aenter__ before __aexit__ in async with (GH-17609) Jan 14, 2020
HISTORY Fix typos mostly in comments, docs and test names (GH-15209) Aug 30, 2019
Porting bpo-30737: Update DevGuide links to new URL (GH-3228) Aug 30, 2017
README bpo-32159: Revert Misc/svnmap.txt (#4639) Nov 29, 2017
README.AIX Replace KB unit with KiB (#4293) Nov 8, 2017
README.coverity Merged revisions 46753-51188 via svnmerge from Aug 11, 2006
README.valgrind bpo-18859: Document --with-valgrind option in README.valgrind (#10591) Nov 20, 2018
SpecialBuilds.txt bpo-36722: Style and grammar edits for ABI news entries (GH-12979) Apr 27, 2019
coverity_model.c bpo-35808: Retire pgen and use pgen2 to generate the parser (GH-11814) Mar 1, 2019
gdbinit bpo-15817: gdbinit: Document commands after defining them (GH-15021) Sep 9, 2019
indent.pro Merged revisions 86134,86315-86316,86390,86424-86425,86428,86550,8656… Nov 26, 2010
python-config.in bpo-38468 : Refactor python-config (#16749) Oct 15, 2019
python-config.sh.in
python-embed.pc.in bpo-36721: Add --embed option to python-config (GH-13500) May 23, 2019
python-wing3.wpr Mark files as executable that are meant as scripts. (GH-15354) Sep 9, 2019
python-wing4.wpr Mark files as executable that are meant as scripts. (GH-15354) Sep 9, 2019
python-wing5.wpr Mark files as executable that are meant as scripts. (GH-15354) Sep 9, 2019
python.man bpo-29535: Remove promize about hash randomization of datetime object… Aug 24, 2019
python.pc.in bpo-36721: Add --embed option to python-config (GH-13500) May 23, 2019
svnmap.txt bpo-32159: Revert Misc/svnmap.txt (#4639) Nov 29, 2017
valgrind-python.supp bpo-38118: Ignore Valgrind false alarm in PyUnicode_Decode() (GH-16651) Oct 8, 2019
vgrindefs Patch #1550800: make exec a function. Sep 6, 2006

README

Python Misc subdirectory
========================

This directory contains files that wouldn't fit in elsewhere.  Some
documents are only of historic importance.

Files found here
----------------

ACKS                    Acknowledgements
gdbinit                 Handy stuff to put in your .gdbinit file, if you use gdb
HISTORY                 News from previous releases -- oldest last
indent.pro              GNU indent profile approximating my C style
NEWS                    News for this release (for some meaning of "this")
Porting                 Mini-FAQ on porting to new platforms
python-config.in        Python script template for python-config
python.man              UNIX man page for the python interpreter
python.pc.in            Package configuration info template for pkg-config
python-wing*.wpr        Wing IDE project file
README                  The file you're reading now
README.AIX              Information about using Python on AIX
README.coverity         Information about running Coverity's Prevent on Python
README.valgrind         Information for Valgrind users, see valgrind-python.supp
SpecialBuilds.txt       Describes extra symbols you can set for debug builds
svnmap.txt              Map of old SVN revs and branches to hg changeset ids,
                        help history-digging
valgrind-python.supp    Valgrind suppression file, see README.valgrind
vgrindefs               Python configuration for vgrind (a generic pretty printer)
You can’t perform that action at this time.