使用 cProfile 在 Python 中分析类的方法?

Posted

技术标签:

【中文标题】使用 cProfile 在 Python 中分析类的方法?【英文标题】:profiling a method of a class in Python using cProfile? 【发布时间】:2011-05-28 09:52:16 【问题描述】:

我想使用 cProfile 在 Python 中分析函数的方法。我尝试了以下方法:

import cProfile as profile

# Inside the class method...
profile.run("self.myMethod()", "output_file")

但它不起作用。如何使用“run”调用 self.method?

【问题讨论】:

How can you profile a Python script?的可能重复 【参考方案1】:
  import cProfile
  p = cProfile.Profile()
  p.runcall(self.myMethod)
  p.print_stats()

Profile 类记录在 here。

【讨论】:

【参考方案2】:

如果您的配置文件下的函数返回值,您需要稍微更改@katrielalex 的出色答案:

...             profile.runctx('val = self.baz()', globals(), locals())
...             print locals()['val']

【讨论】:

【参考方案3】:

编辑:抱歉,没有意识到配置文件调用是类方法中。

run 只是尝试exec 你传递给它的字符串。如果self 未绑定到您正在使用的分析器范围内的任何内容,则不能在run 中使用它!使用runctx方法将调用范围内的局部和全局变量传入profiler:

>>> import time
>>> import cProfile as profile
>>> class Foo(object):
...     def bar(self):
...             profile.runctx('self.baz()', globals(), locals())
...
...     def baz(self):
...             time.sleep(1)
...             print 'slept'
...             time.sleep(2)
...
>>> foo = Foo()
>>> foo.bar()
slept
         5 function calls in 2.999 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    2.999    2.999 <stdin>:5(baz)
        1    0.000    0.000    2.999    2.999 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 method 'disable' of '_lsprof.Profiler' objects
        2    2.999    1.499    2.999    1.499 time.sleep

注意最后一行:time.sleep 是占用时间的内容。

【讨论】:

这在 Mac OS X 上的 Python 2.6.4 上不起作用。我收到错误 NameError: name 'foo' is not defined @user:对不起,我的错。已编辑。 我怎样才能让分析器“挖掘得更深”,即不仅仅是说所有的时间都花在了模块的某个函数上,而是递归地深入研究该模块中调用的函数? 什么意思?分析时间代码从方法调用开始直到返回值。它应该为该模块中调用的每个方法提供结果。你应该看看我的答案,它会给你一个很好的结果图表 太棒了!cProfile.runctx() 传递给当前的globals()locals() 允许对任意方法进行分析——与宣传的完全一样。谢谢你,katrielalex。【参考方案4】:

我不建议分析单个例程,因为这意味着提前知道那里存在问题。

性能问题的一个基本方面是它们是偷偷摸摸的。 它们不在您认为的位置,因为如果它们在,您早就解决了。

最好以真实的工作负载运行整个程序,让分析技术告诉您问题出在哪里。

Here's an example 分析发现问题所在,但不是预期的问题。

【讨论】:

我想要做的就是在这个***例程上运行一个分析器,让分析器真正深入研究函数,而不是仅仅说所有顶部都花在了一些***例程中,因为那是完全没用。 @user248237:对。只需按照我在链接中所说的操作即可。没有分析器可以为您提供更好的信息。 @Mike Dunlavey:不一定。在分析整个代码时,您可能已经确定瓶颈出现在一个函数中。在这种情况下,然后分析该函数以查看那里发生了什么是有意义的.. @Gino:瓶颈是什么?很多人谈论瓶颈,好像“每个人”都知道它们是什么。如果一个大型 C# 应用程序花费 50% 的时间读取 dll 以提取字符串属性,以便它们可以针对当前地理位置进行翻译,那么当您通过查看它不需要的字符串时看到,这是一个瓶颈?探查器会找到它吗? (否)随机暂停会找到它吗? (是)随机暂停将定位任何分析器将定位的任何瓶颈,并且不会定位更多。 @Mike Dunlavey:坦率地说,我不确定你的意思是什么。基本假设是程序员对代码的理解足以辨别什么是相关的,什么是不相关的。当我说一个函数出现瓶颈时,一种明显的可能发生这种情况的方式是,如果我运行一个分析器,而分析器告诉我 90% 的时间都花在了函数 A 上。所以函数 A 是我想要钻取的瓶颈下成。我想知道函数 A 的哪些行占用了大部分时间..【参考方案5】:

使用 profilehooks 装饰器

http://pypi.python.org/pypi/profilehooks

【讨论】:

很方便,但不适用于 Python 3,尽管 2to3 解决了这个问题。 :) Profilehooks 现在支持 Python 3。请参见此处:pypi.python.org/pypi/profilehooks 否。 不要安装重量级依赖项。只需致电cProfile.runctx('self.myMethod()', globals(), locals(), output_file),正如katrielalex 建议的那样应该 是accepted answer。 profilehooks 非常适合分析 Tkinter 应用程序。使用 cProfile 方法,您可以让它直接执行一个函数,如果该函数应该是对 Tkinter.Button 的回调,那么没有重组代码可能不会那么容易。使用 profilehooks,导入 profile 装饰器并将其应用到特定回调中,您可以仅在单击按钮时测试该回调。

以上是关于使用 cProfile 在 Python 中分析类的方法?的主要内容,如果未能解决你的问题,请参考以下文章

在 Python 中分析子进程 Popen 调用

从 shell 环境分析 Python 脚本

从函数中调用 Python cProfile。 (或其他在 Django 中使用 cProfile 的方式)

在python中将函数传递给cProfile的正确方法是啥?

如何使用 cProfile 模块对 python 中的每个函数进行计时?

python模块上的cprofile