Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python cProfile和profile之间的差异&x2014;为什么没有profile.profile.enable()方法?_Python - Fatal编程技术网

Python cProfile和profile之间的差异&x2014;为什么没有profile.profile.enable()方法?

Python cProfile和profile之间的差异&x2014;为什么没有profile.profile.enable()方法?,python,Python,在Python2.7和Python3.6中,我发现这是可行的: from cProfile import Profile; p = Profile(); p.enable() …鉴于这引发了一个例外: from profile import Profile; p = Profile(); p.enable() # --> AttributeError: 'Profile' object has no attribute 'enable' 这让我感到惊讶,因为我认为(以及和的官方文档

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

from cProfile import Profile; p = Profile(); p.enable()
…鉴于这引发了一个例外:

from profile import Profile; p = Profile(); p.enable()

# -->  AttributeError: 'Profile' object has no attribute 'enable'
这让我感到惊讶,因为我认为(以及和的官方文档)这两个模块应该提供相同的程序员接口:

profile
cProfile
模块都提供以下功能:

class-profile.profile(timer=None,timeunit=0.0,subcalls=True,builtins=True)

enable()

开始收集配置文件数据

我错过了什么?使用
profile.profile()
实例的正确方法是什么?

在最新的文档中,他们已经解决了这一问题,指定
enable()
disable()
仅适用于
cProfile
。使用
profile.profile
,您需要使用
run()
调用,而不是
enable()
disable()
。以下是每个项目的样本:

cProfile.Profile:

# 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 -- 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.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 -- 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
    将把配置文件函数的输出推送到标准输出,而
    profile
    不会

  • 最终报告的
    文件名:lineno(函数)
    列的输出将略有不同
    cProfile
    通常会更容易地显示内置函数

    • 然而,在我这里提供的示例中,传入函数实际上可以在
      profile
      的输出中识别,而不是在
      cProfile
      中识别——但是如果使用命名函数,它可以在两个分析器的输出中识别(尽管传入函数的参数仅在
      profile
      的输出中可见)
  • 通过
    cProfile
    profile
    运行相同的函数会产生稍微不同的结果。似乎
    cProfile
    通常会少生成两个函数调用,并为同一个函数提供更高效的时间

  • 使用探查器的可选自定义
    计时器
    时间单位
    参数可以获得微秒精度,而不是默认的毫秒精度。然而,尝试使用这些方法似乎有一些警告:

    • cProfile
      的timeunit函数需要一个整数,而
      profile
      需要一个浮点数。这意味着您不能将
      datetime.now().timestamp()
      直接与
      cProfile
      一起使用,而是必须先将其包装在lambda中以将其转换为完整整数
    • 此外,由于某种原因,
      profile
      似乎无法正确使用
      datetime.now().timestamp()
      格式,即使该格式符合预期。它将打印出负的时间值——我在下面展示。切换到lambda表单将其转换为整数没有帮助,因为
      profile
      需要浮点数
  • 下面是
    profile.profile
    的输出,带有
    datetime.now().timestamp()
    计时器,用于微秒设置

     print(s2.getvalue())
           10015 function calls in -0.020 seconds`
    
     Ordered by: cumulative time
    
     ncalls  tottime  percall  cumtime  percall filename:lineno(function)
          0    0.000             0.000          profile:0(profiler)
          1    0.000    0.000    0.000    0.000 :0(setprofile)
      10011   -0.010   -0.000   -0.010   -0.000 <string>:1(<genexpr>)
          1   -0.010   -0.010   -0.020   -0.020 <string>:1(<module>)
          1   -0.000   -0.000   -0.020   -0.020 :0(exec)
          1   -0.000   -0.000   -0.020   -0.020 profile:0(list(x for x in range(int(10*10*10*10/10*10+10))))
    
    我们现在可以使用
    pr2=profile.profile(timenow,0.000001)
    ,这将输出以下(sane)报告:

    至于为什么我们的自定义计时器函数会给出合理的结果,而
    datetime.now().timestamp()
    profile
    不匹配,首先必须注意的是
    timenow
    不提供
    datetime.now().timestamp()的计时。虽然它提供接近历元时间的时间,但它会少量关闭(不会影响正常剖面运行,因为在同一系统上,增量将相同)。
    timenow
    中使用的手动转换肯定不如
    datetime.now().timestamp()中的效率高。我只能推测后者效率太高,因此,
    profile
    源代码无法正确测量

    TL;博士
    使用
    cProfile
    ,除非您有特定的理由不这样做。官方Python文档还声明建议使用的模块是
    cProfile
    。虽然没有提供具体的理由,但文档似乎暗示,
    cProfile
    可能表现得更好,适合大多数用户的目的(尽管它的语法略为详细)。

    您没有遗漏任何内容。一、 我们也发现了这种情况……并通过查看CPython源代码对其进行了验证。但是我不知道为什么会这样,只是事实上这就是写东西的方式。@martineau+1使用profile.profile()的正确方式是什么--Python3.7和3上也存在已验证的行为。8@jon:当前关于该方法的Python 3.x文档说它仅在
    cProfile
    中可用,这意味着您必须使用
    profile.profile
    run*()
    方法之一。下面是一些.Yep,我发现在概要文件上使用inspect.getmembers()之后,出现了run()方法。我会用这些信息发布一个答案。@jon:FYI,当回复非OP所做的评论时,你需要添加前缀为
    @
    的用户名,这样他们就会收到通知,你已经这样做了。我发现你在这种情况下完全是靠运气(因为有时我会回头看看,如果有的话,我最近自己做出的反应可能是什么)。
    >>> 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}