Python性能分析

4

我用Python写了几个模块来生成阶乘,现在想测试一下运行时间。我在这里找到了一个性能分析的例子,并使用该模板对我的模块进行了性能分析:

import profile #fact

def main():
    x = raw_input("Enter number: ")
    profile.run('fact(int(x)); print')
    profile.run('factMemoized(int(x)); print')

def fact(x):
    if x == 0: return 1
    elif x < 2: return x
    else:
        return x * fact(x-1)

def factMemoized(x):
    if x == 0: return 1
    elif x < 2: return x
    dict1 = dict()
    dict1[0] = 1
    dict1[1] = 1
    for i in range (0, x+1):
        if dict1.has_key(i): pass
        else: dict1[i] = i * dict1[i-1]
    return dict1[x]

if __name__ == "__main__":
    main()

然而,我遇到了以下错误:
Enter number: 10
Traceback (most recent call last):
  File "fact.py", line 32, in <module>
    main()
  File "fact.py", line 7, in main
    profile.run('fact(int(x)); x')
  File "C:\Python27\lib\profile.py", line 70, in run
    prof = prof.run(statement)
  File "C:\Python27\lib\profile.py", line 447, in run
    return self.runctx(cmd, dict, dict)
  File "C:\Python27\lib\profile.py", line 453, in runctx
    exec cmd in globals, locals
  File "<string>", line 1, in <module>
NameError: name 'x' is not defined

请问这里我做错了什么?谢谢! ~ craig

4个回答

7
正如John Gaines Jr所说,“profile.run()”存在一些作用域问题。不过,您可以使用globals()和locals()中的“runctx”,并显式提供上下文:
profile.runctx('fact(int(x)); print', globals(), locals())

Explicit is better than implicit :)


6
分析器接收一个字符串,试图解释它。您的字符串是 profile.run('fact(int(x)); print'),其中的 x 变量只是字符串的一部分,无法解析为变量。您需要将其值复制到字符串中才能使其正常工作。尝试这样做:
profile.run('fact(int(%s)); print' % x)
profile.run('factMemoized(int(%s)); print' % x)

谢谢 @Constantinius!这是我自己的愚蠢瞬间 :) - Craig

3

编辑(删除了我的“答案”,因为Petr Viktorin的答案更合理)。但保留为什么它不像原帖作者期望的那样工作的解释。

查看profile.py(Python 2.7.2)中Profile类的方法,我看到以下内容:

def run(self, cmd):
    import __main__
    dict = __main__.__dict__
    return self.runctx(cmd, dict, dict)

def runctx(self, cmd, globals, locals):
    self.set_cmd(cmd)
    sys.setprofile(self.dispatcher)
    try:
        exec cmd in globals, locals
    finally:
        sys.setprofile(None)
    return self

在runctx()函数中,exec语句的全局和本地字典都被传递给了__main__.__dict__,因此profile.run()只能解析在正在运行的应用程序的顶级字典中定义的变量。

0
您可以使用区域分析器直接对代码进行性能分析。您的代码片段将如下所示:
import region_profiler as rp  # pip install region-profiler

rp.install()

def main():
    x = raw_input("Enter number: ")
    fact(int(x))  # note: direct call
    factMemoized(int(x))

@rp.func(asglobal=True)
def fact(x):
    if x == 0: return 1
    elif x < 2: return x
    else:
        return x * fact(x-1)

@rp.func(asglobal=True)
def factMemoized(x):
    if x == 0: return 1
    elif x < 2: return x
    dict1 = dict()
    dict1[0] = 1
    dict1[1] = 1
    for i in range (0, x+1):
        if dict1.has_key(i): pass
        else: dict1[i] = i * dict1[i-1]
    return dict1[x]

if __name__ == "__main__":
    main()

示例输出:

name                 total  % of total  count       min   average       max
----------------  --------  ----------  -----  --------  --------  --------
<main>             3.601 s     100.00%      1   3.601 s   3.601 s   3.601 s
. fact()            863 us       0.02%      1    863 us    863 us    863 us
. factMemoized()  73.12 us       0.00%      1  73.12 us  73.12 us  73.12 us

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接