ordering are identical to the :meth:`~pstats.Stats.print_callers` method.
+ .. method:: get_stats_profile()
+
+ This method returns an instance of StatsProfile, which contains a mapping
+ of function names to instances of FunctionProfile. Each FunctionProfile
+ instance holds information related to the function's profile such as how
+ long the function took to run, how many times it was called, etc...
+
+ .. versionadded:: 3.9
+ Added the following dataclasses: StatsProfile, FunctionProfile.
+ Added the following function: get_stats_profile.
+
.. _deterministic-profiling:
What Is Deterministic Profiling?
import time
import marshal
import re
+
from enum import Enum
from functools import cmp_to_key
+from dataclasses import dataclass
+from typing import Dict
-__all__ = ["Stats", "SortKey"]
-
+__all__ = ["Stats", "SortKey", "FunctionProfile", "StatsProfile"]
class SortKey(str, Enum):
CALLS = 'calls', 'ncalls'
return obj
+@dataclass(unsafe_hash=True)
+class FunctionProfile:
+ ncalls: int
+ tottime: float
+ percall_tottime: float
+ cumtime: float
+ percall_cumtime: float
+ file_name: str
+ line_number: int
+
+@dataclass(unsafe_hash=True)
+class StatsProfile:
+ '''Class for keeping track of an item in inventory.'''
+ total_tt: float
+ func_profiles: Dict[str, FunctionProfile]
+
class Stats:
"""This class is used for creating reports from data generated by the
Profile class. It is a "friend" of that class, and imports data either
return new_list, msg
+ def get_stats_profile(self):
+ """This method returns an instance of StatsProfile, which contains a mapping
+ of function names to instances of FunctionProfile. Each FunctionProfile
+ instance holds information related to the function's profile such as how
+ long the function took to run, how many times it was called, etc...
+ """
+ func_list = self.fcn_list[:] if self.fcn_list else list(self.stats.keys())
+ if not func_list:
+ return StatsProfile(0, {})
+
+ total_tt = float(f8(self.total_tt))
+ func_profiles = {}
+ stats_profile = StatsProfile(total_tt, func_profiles)
+
+ for func in func_list:
+ cc, nc, tt, ct, callers = self.stats[func]
+ file_name, line_number, 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_profile = FunctionProfile(
+ ncalls,
+ tottime, # time spent in this function alone
+ percall_tottime,
+ cumtime, # time spent in the function plus all functions that this function called,
+ percall_cumtime,
+ file_name,
+ line_number
+ )
+ func_profiles[func_name] = func_profile
+
+ return stats_profile
+
def get_print_list(self, sel_list):
width = self.max_name_len
if self.fcn_list:
import unittest
+
from test import support
from io import StringIO
-import pstats
from pstats import SortKey
-
+import pstats
+import time
+import cProfile
class AddCallersTestCase(unittest.TestCase):
"""Tests for pstats.add_callers helper."""
SortKey.TIME,
'calls')
+ def test_get_stats_profile(self):
+ def pass1(): pass
+ def pass2(): pass
+ def pass3(): pass
+
+ pr = cProfile.Profile()
+ pr.enable()
+ pass1()
+ pass2()
+ pass3()
+ pr.create_stats()
+ ps = pstats.Stats(pr)
+
+ stats_profile = ps.get_stats_profile()
+ funcs_called = set(stats_profile.func_profiles.keys())
+ self.assertIn('pass1', funcs_called)
+ self.assertIn('pass2', funcs_called)
+ self.assertIn('pass3', funcs_called)
if __name__ == "__main__":
unittest.main()