分析 Python 脚本时通过 percall 对 cProfile 输出进行排序

问题描述 投票:0回答:2

我正在使用

python -m cProfile -s calls myscript.py

python -m cProfile -s percall myscript.py
不起作用。

Python 文档说“在统计文档中查找有效的排序值。”:http://docs.python.org/library/profile.html#module-cProfile,我找不到。

python profiling cprofile
2个回答
151
投票

-s 仅使用 在 sort_stats 下找到的键。

calls (call count)
cumulative (cumulative time)
cumtime (cumulative time)
file (file name)
filename (file name)
module (file name)
ncalls (call count)
pcalls (primitive call count)
line (line number)
name (function name)
nfl (name/file/line)
stdname (standard name)
time (internal time)
tottime (internal time)

这是一个例子

python -m cProfile -s tottime myscript.py

0
投票

正如 letmaik 所指出的,此功能有一个开放的错误单。然而,提交者(alexnvdias)已经完成了这项工作,并将他们的代码发布在原始错误单中在 github Pull 请求中。如果你想使用它,你可以继承

pstats.Stats
并实现他们已经提交的内容。对我来说效果很好。

import pstats

class Stats(pstats.Stats):
    # list the tuple indices and directions for sorting,
    # along with some printable description
    sort_arg_dict_default = {
      "calls"            : (((1,-1),              ), "call count"),
      "ncalls"           : (((1,-1),              ), "call count"),
      "cumtime"          : (((4,-1),              ), "cumulative time"),
      "cumulative"       : (((4,-1),              ), "cumulative time"),
      "file"             : (((6, 1),              ), "file name"),
      "filename"         : (((6, 1),              ), "file name"),
      "line"             : (((7, 1),              ), "line number"),
      "module"           : (((6, 1),              ), "file name"),
      "name"             : (((8, 1),              ), "function name"),
      "nfl"              : (((8, 1),(6, 1),(7, 1),), "name/file/line"),
      "pcalls"           : (((0,-1),              ), "primitive call count"),
      "stdname"          : (((9, 1),              ), "standard name"),
      "time"             : (((2,-1),              ), "internal time"),
      "tottime"          : (((2,-1),              ), "internal time"),
      "cumulativepercall": (((5,-1),              ), "cumulative time per call"),
      "totalpercall"     : (((3,-1),              ), "total time per call"),
      }


    def sort_stats(self, *field):
      if not field:
        self.fcn_list = 0
        return self
      if len(field) == 1 and isinstance(field[0], int):
        # Be compatible with old profiler
        field = [ {-1: "stdname",
                    0:  "calls",
                    1:  "time",
                    2:  "cumulative"}[field[0]] ]
      elif len(field) >= 2:
        for arg in field[1:]:
          if type(arg) != type(field[0]):
            raise TypeError("Can't have mixed argument type")

      sort_arg_defs = self.get_sort_arg_defs()

      sort_tuple = ()
      self.sort_type = ""
      connector = ""
      for word in field:
        if isinstance(word, pstats.SortKey):
          word = word.value
        sort_tuple = sort_tuple + sort_arg_defs[word][0]
        self.sort_type += connector + sort_arg_defs[word][1]
        connector = ", "
  
      stats_list = []
      for func, (cc, nc, tt, ct, callers) in self.stats.items():
        if nc == 0:
          npc = 0
        else:
          npc = float(tt)/nc

        if cc == 0:
          cpc = 0
        else:
          cpc = float(ct)/cc

        stats_list.append((cc, nc, tt, npc, ct, cpc) + func +
                          (pstats.func_std_string(func), func))

      stats_list.sort(key=pstats.cmp_to_key(pstats.TupleComp(sort_tuple).compare))

      self.fcn_list = fcn_list = []
      for tuple in stats_list:
        fcn_list.append(tuple[-1])
      return self

s = Stats('test.dat')
s.sort_stats('totalpercall')
s.print_stats()

结果:

Mon Apr 29 12:50:37 2024    test.dat

     2003 function calls in 0.058 seconds

Ordered by: total time per call

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    1    0.001    0.001    0.058    0.058 test.py:2(<module>)
 1000    0.029    0.000    0.029    0.000 test.py:2(add)
 1000    0.028    0.000    0.028    0.000 test.py:8(sub)
    1    0.000    0.000    0.058    0.058 {built-in method builtins.exec}
    1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
© www.soinside.com 2019 - 2024. All rights reserved.