Python 性能分析
我写了几个用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
你们知道我哪里出错了吗?谢谢!
4 个回答
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()只能找到在运行的应用程序顶层字典中定义的变量。
7
正如John Gaines Jr.所说,profile.run()
在作用域方面有一些问题。不过,你可以直接使用runctx
,配合globals()和locals(),明确地提供上下文:
profile.runctx('fact(int(x)); print', globals(), locals())
明确总比模糊好 :)
6
这个分析工具接收到一个字符串,然后试图去理解它。你给的字符串是 profile.run('fact(int(x)); print')
,而里面的 x
只是字符串的一部分,不能被当作一个变量来处理。为了让它正常工作,你需要把 x
的值直接放到字符串里。试试这样做:
profile.run('fact(int(%s)); print' % x)
profile.run('factMemoized(int(%s)); print' % x)