首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >cProfile和profile -why无profile.Profile.enable()方法的区别?

cProfile和profile -why无profile.Profile.enable()方法的区别?
EN

Stack Overflow用户
提问于 2018-10-25 22:26:14
回答 1查看 391关注 0票数 4

在Python2.7和Python3.6中,我发现这是可行的:

代码语言:javascript
复制
from cProfile import Profile; p = Profile(); p.enable()

...whereas这会引发一个异常:

代码语言:javascript
复制
from profile import Profile; p = Profile(); p.enable()

# -->  AttributeError: 'Profile' object has no attribute 'enable'

这让我感到惊讶,因为我认为(以及Python 3Python 2状态的官方文档)这两个模块应该提供相同的程序员接口:

profilecProfile模块都提供了以下功能: ..。 class profile.Profile(timer=None, timeunit=0.0, subcalls=True, builtins=True) ..。 enable() 开始收集个人资料。

我遗漏了什么?使用profile.Profile()实例的正确方法是什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-07 04:12:41

Python 3.8和更新的文档中,他们已经修正了这一点,以指定enable()disable()只能在cProfile中使用。对于profile.Profile,您需要使用run()调用,而不是enable()disable()。以下是每个样本的样本:

cProfile.Profile:

代码语言:javascript
复制
# cProfile.Profile -- control with enable() and disable()
from datetime import datetime
import cProfile, pstats, io
sortby = 'cumulative'
pr1 = cProfile.Profile(lambda: int(datetime.now().timestamp()*1000000), 0.000001)
pr1.enable()
list(x for x in range(int(10*10*10*10/10*10+10)))
pr1.disable()
s1 = io.StringIO()
ps1 = pstats.Stats(pr1, stream=s1).sort_stats(sortby)
ps1.print_stats()
print(s1.getvalue())

profile.Profile:

代码语言:javascript
复制
# profile.Profile -- control with run()
from datetime import datetime
import profile, pstats, io
sortby = 'cumulative'
pr2 = profile.Profile(datetime.now().timestamp, 0.000001)
pr2.run('list(x for x in range(int(10*10*10*10/10*10+10)))')
s2 = io.StringIO()
ps2 = pstats.Stats(pr2, stream=s2).sort_stats(sortby)
ps2.print_stats()
print(s2.getvalue())

下面是我在这两种形式之间观察到的一些行为差异:

  • cProfile会将配置函数的输出推到stdout,而profile不会。
  • 最后报告的filename:lineno(function)列的输出略有不同。cProfile通常会更容易地显示内置函数。
代码语言:javascript
复制
- In the example I provided here, however, the passed in function is actually identifiable in `profile`'s output and _not_ in `cProfile`'s -- but if using a named function, it is identifiable in _both_ profilers' output (although the passed in _arguments_ to the function are only visible from `profile`'s output).
  • 通过cProfileprofile运行相同的函数,结果略有不同。似乎cProfile一般会生成两个更少的函数调用,并且会为相同的函数提供更有效的时间。
  • 使用分析器的可选自定义timertimeunit参数可以提供获得微秒精度相对于默认毫秒精度的好处。然而,试图使用这些方法似乎附带了一些注意事项:
代码语言:javascript
复制
- `cProfile`'s timeunit function requires an integer, whereas `profile` expects  a floating point number. This means you can't use `datetime.now().timestamp()` directly with `cProfile`, but must rather wrap it in a lambda to convert it to a full integer first.
- Additionally, for some reason `profile` seems to not work correctly with `datetime.now().timestamp()` even though that's in the format it's expecting. It will print out negative time values -- I show this below. Switching to the lambda form to convert it to integer doesn't help, as `profile` expects the floating point number.
  • 下面是profile.Profiledatetime.now().timestamp()计时器的输出,用于提供微秒。 打印(s2.getvalue()) 10015函数调用in -0.020次`,顺序为:累积时间n调用全时每次调用和时间调用文件名:lineno(函数)0 0.000 0.000配置文件:0(分析器)1 0.000 0.000 0.000 :0(setprofile) 10011 -0.010 -0.000 -0.000 :1()1 -0.010 -0.010 -0.020 -0.020 :1() 1 -0.000 -0.000 -0.020 -0.020 :0(exec) 1 -0.000 -0.000 -0.020 -0.020 -0.020-0(x在范围内(int(10*10*10*10*10*10+10)
  • 但是,可以通过提供自定义计时器函数来解决这个问题(它甚至可以围绕datetime.now()来提供与datetime.now().timestamp()完全相同的输出格式),原因我无法解释。

例如,如果我们定义:

代码语言:javascript
复制
def timenow():
   now = datetime.now()
   return (((now.year-1970) * 31557600) + (now.month * 2629800) + 
           (now.day * 86400) + (now.hour * 3600) + (now.minute * 60) +
           now.second + (now.microsecond * 0.000001))

我们现在可以使用pr2 = profile.Profile(timenow, 0.000001),它将输出以下(正常)报告:

代码语言:javascript
复制
>>> print(s2.getvalue())
         10015 function calls in 0.041 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.006    0.006    0.041    0.041 profile:0(list(x for x in range(int(10*10*10*10/10*10+10))))
        1    0.000    0.000    0.035    0.035 :0(exec)
        1    0.017    0.017    0.035    0.035 <string>:1(<module>)
    10011    0.018    0.000    0.018    0.000 <string>:1(<genexpr>)
        1    0.001    0.001    0.001    0.001 :0(setprofile)
        0    0.000             0.000          profile:0(profiler)

cProfile的输出(使用上面定义的自定义lambda计时器)相比,我们有:

代码语言:javascript
复制
>>> print(s1.getvalue())
         10013 function calls in 0.031 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    10011    0.031    0.000    0.031    0.000 <stdin>:1(<genexpr>)
        1    0.000    0.000    0.000    0.000 <stdin>:1(<module>)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

至于为什么我们的自定义计时器函数给出了合理的结果,而datetime.now().timestamp()没有使用profile,首先必须注意的是,timenow没有为datetime.now().timestamp()提供时间。虽然它提供了接近时代的时间,但它的数量很小(不应该影响正常配置文件的运行,因为三角洲在同一个系统上是相同的)。timenow中使用的手动转换也肯定不如在datetime.now().timestamp()中使用的高效。我只能推测后者的效率太高,而且profile源代码在某种程度上没有进行适当的度量。

TL;DR

除非您有特定的理由不使用cProfile,否则使用它。官方的Python还指出,推荐的模块是cProfile。虽然没有提供具体的理由,但是文档似乎暗示cProfile可能表现得更好,适合大多数用户的使用(尽管它是一种稍微冗长的语法)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52998945

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档