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.
asyncio bpo-38356: Fix ThreadedChildWatcher thread leak in test_asyncio (GH-1… Jan 12, 2020
collections bpo-36321: Fix misspelled attribute name in namedtuple() (GH-16858) Oct 20, 2019
concurrent bpo-31783: Fix a race condition creating workers during shutdown (#13171 Jun 28, 2019
ctypes bpo-16575: Disabled checks for union types being passed by value. (GH… Jan 12, 2020
curses [3.9] bpo-37116: Use PEP 570 syntax for positional-only parameters. (G… Jun 5, 2019
dbm bpo-36232: Improve error message on dbm.open() when the db doesn't ex… Apr 29, 2019
distutils bpo-38914 Do not require email field in setup.py. (GH-17388) Dec 23, 2019
email bpo-38708: email: Fix a potential IndexError when parsing Message-ID (G… Dec 9, 2019
encodings bpo-38945: UU Encoding: Don't let newline in filename corrupt the out… Dec 2, 2019
ensurepip bpo-37449: Move ensurepip off of pkgutil and to importlib.resources (G… Sep 13, 2019
html bpo-37328: remove deprecated HTMLParser.unescape (GH-14186) Aug 27, 2019
http bpo-35292: Avoid calling mimetypes.init when http.server is imported (G… Jan 8, 2020
idlelib Minor formatting improvements and fixes to idle.rst (GH-17165) Jan 5, 2020
importlib bpo-39156: Break up COMPARE_OP into four logically distinct opcodes. (G… Jan 14, 2020
json bpo-29636: json.tool: Add document for indentation options. (GH-17482) Dec 7, 2019
lib2to3 bpo-39313: Add an option to RefactoringTool for using exec as a funct… Jan 12, 2020
logging bpo-39292: Add missing syslog facility codes. (GH-17945) Jan 10, 2020
msilib Remove binding of captured exceptions when not used to reduce the cha… Nov 19, 2019
multiprocessing bpo-38546: multiprocessing tests stop the resource tracker (GH-17641) Dec 17, 2019
pydoc_data Python 3.9.0a2 Dec 18, 2019
site-packages Issue #29283: Delete accidentally added Lib/site-packages/README Jan 30, 2017
sqlite3 bpo-38185: Fixed case-insensitive string comparison in sqlite3.Row in… Sep 17, 2019
test bpo-37958: Adding get_profile_dict to pstats (GH-15495) Jan 15, 2020
tkinter bpo-39152: add missing ttk.Scale.configure return value (GH-17815) Jan 5, 2020
turtledemo Mark files as executable that are meant as scripts. (GH-15354) Sep 9, 2019
unittest Improve test coverage for AsyncMock. (GH-17906) Jan 15, 2020
urllib bpo-39057: Fix urllib.request.proxy_bypass_environment(). (GH-17619) Jan 5, 2020
venv bpo-38901: Allow setting a venv's prompt to the basename of the curre… Jan 14, 2020
wsgiref bpo-8138: Initialize wsgiref's SimpleServer as single-threaded (GH-12977 May 24, 2019
xml bpo-20928: support base-URL and recursive includes in etree.ElementIn… Nov 25, 2019
xmlrpc bpo-38786: Add parsing of https links to pydoc (GH-17143) Nov 13, 2019
__future__.py bpo-35526: make __future__.barry_as_FLUFL mandatory for Python 4.0 (#… Dec 19, 2018
__phello__.foo.py Fix the frozen bytecode for __hello__ (betcha didn't know that existed Oct 18, 2001
_aix_support.py bpo-38021: Modify AIX platform_tag so it covers PEP 425 needs (GH-17303) Dec 15, 2019
_bootlocale.py bpo-29240: PEP 540: Add a new UTF-8 Mode (#855) Dec 13, 2017
_collections_abc.py bpo-37116: Use PEP 570 syntax for positional-only parameters. (GH-13700) Jun 1, 2019
_compat_pickle.py bpo-37757: Disallow PEP 572 cases that expose implementation details (G… Aug 25, 2019
_compression.py Issue #23529: Limit the size of decompressed data when reading from Apr 10, 2015
_markupbase.py #13576: add tests about the handling of (possibly broken) condcoms. Dec 19, 2011
_osx_support.py bpo-35257: Avoid leaking LTO linker flags into distutils (GH-10900) Dec 19, 2018
_py_abc.py bpo-37116: Use PEP 570 syntax for positional-only parameters. (GH-13700) Jun 1, 2019
_pydecimal.py bpo-36793: Remove unneeded __str__ definitions. (GH-13081) May 6, 2019
_pyio.py closes bpo-27805: Ignore ESPIPE in initializing seek of append-mode f… Nov 12, 2019
_sitebuiltins.py #9364: Improve the text printed by help(pydoc) and help(help). Apr 19, 2014
_strptime.py Fix outdated comment in _strptime.py (GH-17929) Jan 12, 2020
_threading_local.py bpo-37116: Use PEP 570 syntax for positional-only parameters. (GH-13700) Jun 1, 2019
_weakrefset.py bpo-36949: Implement __repr__ on WeakSet (GH-13415) May 20, 2019
abc.py bpo-35609: Remove examples for deprecated decorators in the abc modul… Dec 31, 2018
aifc.py bpo-37320: Remove openfp() of aifc, sunau and wave (GH-14169) Jun 17, 2019
antigravity.py Change the xkcd link in comment over https. (GH-5452) Sep 14, 2018
argparse.py Defer import of shutil which only needed for help and usage (GH-17334) Nov 22, 2019
ast.py bpo-39158: ast.literal_eval() doesn't support empty sets (GH-17742) Jan 3, 2020
asynchat.py Remove binding of captured exceptions when not used to reduce the cha… Nov 19, 2019
asyncore.py bpo-15999: Always pass bool instead of int to socket.setblocking(). (G… Sep 1, 2019
base64.py bpo-39055: Reject a trailing \n in base64.b64decode() with validate=T… Jan 5, 2020
bdb.py Fix typos mostly in comments, docs and test names (GH-15209) Aug 30, 2019
binhex.py Issue #23865: close() methods in multiple modules now are idempotent … Apr 10, 2015
bisect.py bpo-38626: Add comment explaining why __lt__ is used. (GH-16978) Oct 29, 2019
bz2.py bpo-35128: Fix spacing issues in warning.warn() messages. (GH-10268) Nov 1, 2018
cProfile.py [3.9] bpo-37116: Use PEP 570 syntax for positional-only parameters. (G… Jun 5, 2019
calendar.py bpo-28292: Mark calendar.py helper functions as private. (GH-15113) Aug 4, 2019
cgi.py bpo-20504 : in cgi.py, fix bug when a multipart/form-data request has… ( Sep 11, 2019
cgitb.py bpo-33311: Do not display parameters displayed in parentheses for mod… May 9, 2018
chunk.py bpo-29762: More use "raise from None". (#569) Apr 5, 2017
cmd.py Issue #18200: Back out usage of ModuleNotFoundError (8d28d44f3a9a) Jul 4, 2013
code.py Fix documentation in code.py (GH-17988) Jan 14, 2020
codecs.py bpo-33361: Fix bug with seeking in StreamRecoders (GH-8278) May 31, 2019
codeop.py bpo-36820: Break unnecessary cycle in socket.py, codeop.py and dyld.py ( Dec 6, 2019
colorsys.py Issue #14323: Expanded the number of digits in the coefficients for the Aug 6, 2013
compileall.py bpo-38470: Fix test_compileall.test_compile_dir_maxlevels() (GH-16789) Oct 15, 2019
configparser.py fix typo in configparser doc (GH-12154) Mar 4, 2019
contextlib.py [3.9] bpo-37116: Use PEP 570 syntax for positional-only parameters. (G… Jun 5, 2019
contextvars.py bpo-32436: Implement PEP 567 (#5027) Jan 23, 2018
copy.py bpo-38293: Allow shallow and deep copying of property objects (GH-16438) Jan 12, 2020
copyreg.py bpo-33138: Change standard error message for non-pickleable and non-c… Oct 31, 2018
crypt.py closes bpo-38402: Check error of primitive crypt/crypt_r. (GH-16599) Oct 8, 2019
csv.py bpo-27497: Add return value to csv.DictWriter.writeheader (GH-12306) May 10, 2019
dataclasses.py bpo-34776: Fix dataclasses to support __future__ "annotations" mode (#… Dec 9, 2019
datetime.py bpo-38155: Add __all__ to datetime module (GH-16203) Sep 19, 2019
decimal.py Whitespace. Sep 10, 2014
difflib.py bpo-38738: Fix formatting of True and False. (GH-17083) Nov 12, 2019
dis.py bpo-38115: Deal with invalid bytecode offsets in lnotab (GH-16079) Sep 28, 2019
doctest.py bpo-36406: Handle namespace packages in doctest (GH-12520) Dec 13, 2019
enum.py bpo-38045: Improve the performance of _decompose() in enum.py (GH-16483) Nov 26, 2019
filecmp.py Remove binding of captured exceptions when not used to reduce the cha… Nov 19, 2019
fileinput.py bpo-37330: open() no longer accept 'U' in file mode (GH-16959) Oct 28, 2019
fnmatch.py bpo-32775: Fix regular expression warnings in fnmatch. (#5583) Feb 9, 2018
formatter.py Issue #25407: Drop the mention of the formatter module being removed Oct 16, 2015
fractions.py Add a minor `Fraction.__hash__()` optimization (GH-15313) Aug 17, 2019
ftplib.py bpo-39259: ftplib.FTP/FTP_TLS now reject timeout = 0 (GH-17959) Jan 13, 2020
functools.py bpo-38565: add new cache_parameters method for lru_cache (GH-16916) Nov 12, 2019
genericpath.py bpo-38807: Add os.PathLike to exception message raised by _check_arg_… Nov 19, 2019
getopt.py Issue #25523: Correct "a" article to "an" article Nov 2, 2015
getpass.py Remove binding of captured exceptions when not used to reduce the cha… Nov 19, 2019
gettext.py bpo-36239: Skip comments in gettext infos (GH-12255) May 9, 2019
glob.py bpo-37363: Add audit events for a range of modules (GH-14301) Jun 24, 2019
gzip.py bpo-28286: Deprecate opening GzipFile for writing implicitly. (GH-16417) Nov 16, 2019
hashlib.py bpo-38153: Normalize hashlib algorithm names (GH-16083) Sep 13, 2019
heapq.py bpo-29984: Improve 'heapq' test coverage (GH-992) Jun 1, 2019
hmac.py bpo-33604: Raise TypeError on missing hmac arg. (GH-16805) Oct 18, 2019
imaplib.py bpo-38615: Add timeout parameter for IMAP4 and IMAP4_SSL constructor (G… Jan 7, 2020
imghdr.py Issue #28228: imghdr now supports pathlib Oct 1, 2016
imp.py bpo-37330: open() no longer accept 'U' in file mode (GH-16959) Oct 28, 2019
inspect.py Remove unnecessary variable definition (GH-17368) Nov 24, 2019
io.py bpo-36842: Implement PEP 578 (GH-12613) May 23, 2019
ipaddress.py bpo-32820: Simplify __format__ implementation for ipaddress. (GH-16378) Sep 27, 2019
keyword.py bpo-36143: Regenerate Lib/keyword.py from the Grammar and Tokens file… Mar 25, 2019
linecache.py Issue #23838: linecache now clears the cache and returns an empty res… Apr 1, 2015
locale.py bpo-18378: Recognize "UTF-8" as a valid name in locale._parse_localen… Aug 29, 2019
lzma.py Issue #28229: lzma module now supports pathlib Oct 4, 2016
mailbox.py bpo-31522: mailbox.get_string: pass `from_` parameter to `get_bytes` (#… Oct 19, 2018
mailcap.py #14977: Make mailcap respect the order of the lines in the mailcap file. Sep 10, 2016
mimetypes.py bpo-39299: Add more tests for mimetypes and its cli. (GH-17949) Jan 13, 2020
modulefinder.py bpo-37032: Add CodeType.replace() method (GH-13542) May 24, 2019
netrc.py bpo-28334: netrc() now uses expanduser() to find .netrc file (GH-4537) Nov 25, 2017
nntplib.py bpo-39259: nntplib.NNTP/NNTP_SSL now reject timeout = 0 (GH-17936) Jan 11, 2020
ntpath.py bpo-38453: Ensure ntpath.realpath correctly resolves relative paths (G… Nov 15, 2019
nturl2path.py bpo-29836: Remove nturl2path from test_sundry and amend the module do… Mar 17, 2017
numbers.py Fix miscellaneous typos (#4275) Nov 5, 2017
opcode.py bpo-39156: Break up COMPARE_OP into four logically distinct opcodes. (G… Jan 14, 2020
operator.py bpo-37116: Use PEP 570 syntax for positional-only parameters. (GH-13700) Jun 1, 2019
optparse.py bpo-34605: Avoid master/slave terms (GH-9101) Sep 7, 2018
os.py bpo-38878: Fix os.PathLike __subclasshook__ (GH-17336) Dec 22, 2019
pathlib.py bpo-38811: Check for presence of os.link method in pathlib (GH-17225) Dec 16, 2019
pdb.py bpo-38723: Pdb._runscript should use io.open_code() instead of open() ( Nov 12, 2019
pickle.py bpo-38876: Raise pickle.UnpicklingError when loading an item from mem… Nov 24, 2019
pickletools.py bpo-36785: PEP 574 implementation (GH-7076) May 26, 2019
pipes.py Merge doc changes from 3.2 (#10454, #12298) Sep 1, 2011
pkgutil.py closes bpo-31650: PEP 552 (Deterministic pycs) implementation (#4575) Dec 9, 2017
platform.py bpo-35389: platform.platform() calls libc_ver() without executable (G… Jun 27, 2019
plistlib.py bpo-36409: Remove old plistlib API deprecated in 3.4 (GH-15615) Sep 5, 2019
poplib.py bpo-39259: poplib now rejects timeout = 0 (GH-17912) Jan 10, 2020
posixpath.py bpo-35755: Remove current directory from posixpath.defpath (GH-11586) Apr 17, 2019
pprint.py bpo-37376: pprint support for SimpleNamespace (GH-14318) Jun 26, 2019
profile.py [3.9] bpo-37116: Use PEP 570 syntax for positional-only parameters. (G… Jun 5, 2019
pstats.py bpo-37958: Adding get_profile_dict to pstats (GH-15495) Jan 15, 2020
pty.py Issue #18200: Back out usage of ModuleNotFoundError (8d28d44f3a9a) Jul 4, 2013
py_compile.py bpo-22640: Add silent mode to py_compile.compile() (GH-12976) May 28, 2019
pyclbr.py Fix typos in docs and docstrings (GH-13745) Jun 2, 2019
pydoc.py bpo-38786: Add parsing of https links to pydoc (GH-17143) Nov 13, 2019
queue.py bpo-37394: Fix pure Python implementation of the queue module (GH-14351) Jun 25, 2019
quopri.py bpo-15999: Clean up of handling boolean arguments. (GH-15610) Sep 1, 2019
random.py bpo-38881: choices() raises ValueError when all weights are zero (GH-… Nov 23, 2019
re.py bpo-36548: Improve the repr of re flags. (GH-12715) May 31, 2019
reprlib.py bpo-31370: Remove support for threads-less builds (#3385) Sep 7, 2017
rlcompleter.py Merge 3.5 Feb 4, 2016
runpy.py bpo-38722: Runpy use io.open_code() (GH-17234) Nov 18, 2019
sched.py bpo-31370: Remove support for threads-less builds (#3385) Sep 7, 2017
secrets.py Issue #29061: secrets.randbelow() would hang with a negative input Dec 30, 2016
selectors.py bpo-30624 remaining bare except (#2108) Jun 12, 2017
shelve.py Fix misleading docsting of shelve.open(). (GH-6427) Apr 9, 2018
shlex.py Add docstring for shlex.split (GH-16740) Oct 31, 2019
shutil.py bpo-38688, shutil.copytree: consume iterator and create list of entri… Nov 27, 2019
signal.py bpo-34282: Fix Enum._convert shadowing members named _convert (GH-8568) Sep 12, 2018
site.py Fix typo in site module (GH-17597) Dec 14, 2019
smtpd.py bpo-35800: Deprecate smtpd.MailmanProxy (GH-11675) Oct 12, 2019
smtplib.py bpo-39329: Add timeout parameter for smtplib.LMTP constructor (GH-17998) Jan 14, 2020
sndhdr.py bpo-31985: Deprecate openfp in aifc, sunau, and wave (#4344) Nov 10, 2017
socket.py Fix host in address of socket.create_server example. (GH-17706) Jan 11, 2020
socketserver.py Fix typo in Lib/socketserver.py (GH-17024) Nov 16, 2019
sre_compile.py Simplify flags checks in sre_compile.py. (GH-9718) Oct 5, 2018
sre_constants.py bpo-36793: Remove unneeded __str__ definitions. (GH-13081) May 6, 2019
sre_parse.py bpo-37723: Fix performance regression on regular expression parsing. (G… Jul 31, 2019
ssl.py bpo-37463: match_hostname requires quad-dotted IPv4 (GH-14499) Jul 2, 2019
stat.py bpo-38109: Add missing constants to Lib/stat.py (GH-16665) Oct 10, 2019
statistics.py bpo-38385: Fix iterator/iterable terminology in statistics docs (GH-1… Nov 12, 2019
string.py bpo-38208: Simplify string.Template by using __init_subclass__(). (GH… Oct 21, 2019
stringprep.py Merged revisions 55007-55179 via svnmerge from May 7, 2007
struct.py Issue #17804: New function ``struct.iter_unpack`` allows for streamin… Apr 26, 2013
subprocess.py bpo-38630: Fix subprocess.Popen.send_signal() race condition (GH-16984) Jan 15, 2020
sunau.py bpo-37320: Remove openfp() of aifc, sunau and wave (GH-14169) Jun 17, 2019
symbol.py bpo-35766: Merge typed_ast back into CPython (GH-11645) Jan 31, 2019
symtable.py bpo-34983: Expose symtable.Symbol.is_nonlocal() in the symtable module ( Oct 20, 2018
sysconfig.py bpo-38021: Modify AIX platform_tag so it covers PEP 425 needs (GH-17303) Dec 15, 2019
tabnanny.py bpo-30166: Import command-line parsing modules only when needed. (#1293) May 4, 2017
tarfile.py Add missing docstrings for TarInfo objects (#12555) Mar 27, 2019
telnetlib.py bpo-37363: Add audit events for a range of modules (GH-14301) Jun 24, 2019
tempfile.py bpo-39019: Implement missing __class_getitem__ for SpooledTemporaryFi… Dec 30, 2019
textwrap.py bpo-30754: Document textwrap.dedent blank line behavior. (GH-14469) Jun 30, 2019
this.py Fix most trivially-findable print statements. Feb 9, 2007
threading.py bpo-15999: Clean up of handling boolean arguments. (GH-15610) Sep 1, 2019
timeit.py bpo-28240: timeit: Update repeat() doc (GH-7419) Jun 6, 2018
token.py bpo-35975: Support parsing earlier minor versions of Python 3 (GH-12086) Mar 7, 2019
tokenize.py bpo-5028: Fix up rest of documentation for tokenize documenting line (G… May 30, 2019
trace.py [3.9] bpo-37116: Use PEP 570 syntax for positional-only parameters. (G… Jun 5, 2019
traceback.py bpo-37685: Fixed __eq__, __lt__ etc implementations in some classes. (G… Aug 8, 2019
tracemalloc.py bpo-37961, tracemalloc: add Traceback.total_nframe (GH-15545) Oct 15, 2019
tty.py final round of __all__ lists (I hope) - skipped urllib2 because Moshe… Mar 1, 2001
turtle.py Fix typos in docs and docstrings (GH-13745) Jun 2, 2019
types.py bpo-37032: Add CodeType.replace() method (GH-13542) May 24, 2019
typing.py Better runtime TypedDict (GH-17214) Nov 24, 2019
uu.py bpo-38945: UU Encoding: Don't let newline in filename corrupt the out… Dec 2, 2019
uuid.py bpo-28009: Fix uuid.uuid1() and uuid.get_node() on AIX (GH-8672) Sep 26, 2019
warnings.py bpo-39056: Fix handling invalid warning category in the -W option. (G… Jan 5, 2020
wave.py Fix a typo in wave module docstring (GH-17009) Nov 5, 2019
weakref.py bpo-38761: Register WeakSet as a MutableSet (GH-17104) Nov 11, 2019
webbrowser.py bpo-37363: Add audit events for a range of modules (GH-14301) Jun 24, 2019
xdrlib.py Issue #11694: Raise ConversionError in xdrlib as documented Oct 10, 2014
zipapp.py bpo-31638: Add compression support to zipapp (GH-3819) Sep 29, 2017
zipfile.py bpo-37523: Raise ValueError for I/O operations on a closed zipfile.Zi… Nov 30, 2019
zipimport.py bpo-39033: Fix NameError in zipimport during hash validation (GH-17588) Dec 15, 2019
You can’t perform that action at this time.