使用 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 cProfile。 (或其他在 Django 中使用 cProfile 的方式)
在python中将函数传递给cProfile的正确方法是啥?