有没有简单的方法来testingpython脚本?
通常我使用shell命令time
。 我的目的是testing数据是小的,中等的,大的还是非常大的集合,多less时间和内存的使用情况。
任何工具为Linux或只是Python来做到这一点?
看看timeit , python profiler和pycallgraph 。
timeit
def test(): """Stupid test function""" lst = [] for i in range(100): lst.append(i) if __name__ == '__main__': import timeit print(timeit.timeit("test()", setup="from __main__ import test"))
本质上,您可以将它作为一个stringparameter passing给python代码,它将在指定的时间内运行并打印执行时间。 文档中的重要部分:
timeit.timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000)
用给定的语句, 设置代码和定时器函数创build一个
Timer
实例,并运行带有数字执行的timeit
方法。
…和:
Timer.timeit(number=1000000)
主要语句的时间编号执行。 这会执行一次setup语句,然后返回多次执行main语句所花费的时间,以秒为单位进行度量。 论点是循环次数,默认为100万。 主语句,设置语句和要使用的定时器函数被传递给构造函数。
注意
默认情况下,
timeit
暂时closuresgarbage collection
。 这种方法的优点是使独立的时间更具可比性。 这个缺点是GC可能是被测function性能的重要组成部分。 如果是这样,可以重新启用GC作为安装string中的第一条语句。 例如:
timeit.Timer('for i in xrange(10): oct(i)', 'gc.enable()').timeit()
剖析
分析会给你一个更详细的想法。 以下是官方文档中的“即时示例”:
import cProfile import re cProfile.run('re.compile("foo|bar")')
哪个会给你:
197 function calls (192 primitive calls) in 0.002 seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.000 0.000 0.001 0.001 <string>:1(<module>) 1 0.000 0.000 0.001 0.001 re.py:212(compile) 1 0.000 0.000 0.001 0.001 re.py:268(_compile) 1 0.000 0.000 0.000 0.000 sre_compile.py:172(_compile_charset) 1 0.000 0.000 0.000 0.000 sre_compile.py:201(_optimize_charset) 4 0.000 0.000 0.000 0.000 sre_compile.py:25(_identityfunction) 3/1 0.000 0.000 0.000 0.000 sre_compile.py:33(_compile)
这两个模块应该给你一个关于在哪里寻找瓶颈的想法。
此外,要掌握profile
的输出,看看这个职位
pycallgraph
该模块使用graphviz来创build如下的调用图:
您可以通过颜色轻松查看哪些path最耗时。 您可以使用pycallgraph API或使用打包的脚本创build它们:
pycallgraph graphviz -- ./mypythonscript.py
虽然开销是相当可观的。 因此,对于已经很长时间运行的stream程,创build图表需要一些时间。
我使用一个简单的装饰器来定时function
def st_time(func): """ st decorator to calculate the total time of a func """ def st_func(*args, **keyArgs): t1 = time.time() r = func(*args, **keyArgs) t2 = time.time() print "Function=%s, Time=%s" % (func.__name__, t2 - t1) return r return st_func
我通常会快速地time ./script.py
来查看需要多长时间。 这并不显示你的内存,但至less不是默认的。 您可以使用/usr/bin/time -v ./script.py
来获取大量信息,包括内存使用情况。
timeit
模块很慢很奇怪,所以我写了这个:
def timereps(reps, func): from time import time start = time() for i in range(0, reps): func() end = time() return (end - start) / reps
例:
import os listdir_time = timereps(10000, lambda: os.listdir('/')) print "python can do %d os.listdir('/') per second" % (1 / listdir_time)
对我来说,它说:
python can do 40925 os.listdir('/') per second
这是一种原始的基准testing,但已经足够好了。
看一下鼻子和它的一个插件,特别是这个插件。
一旦安装,鼻子就是你的path中的脚本,你可以调用一个包含一些python脚本的目录:
$: nosetests
这将在当前目录中的所有python文件中查找,并执行它认为是testing的任何函数:例如,它可以识别其名称中包含单词test_的任何函数作为testing。
所以你可以创build一个名为test_yourfunction.py的python脚本,并在其中写下如下内容:
$: cat > test_yourfunction.py def test_smallinput(): yourfunction(smallinput) def test_mediuminput(): yourfunction(mediuminput) def test_largeinput(): yourfunction(largeinput)
那么你必须跑步
$: nosetest --with-profile --profile-stats-file yourstatsprofile.prof testyourfunction.py
并阅读configuration文件,使用这个python行:
python -c "import hotshot.stats ; stats = hotshot.stats.load('yourstatsprofile.prof') ; stats.sort_stats('time', 'calls') ; stats.print_stats(200)"
内存分析器满足您所有的内存需求。
https://pypi.python.org/pypi/memory_profiler
运行一个点子安装:
pip install memory_profiler
导入库:
import memory_profiler
添加一个装饰器到你想要的configuration文件:
@profile def my_func(): a = [1] * (10 ** 6) b = [2] * (2 * 10 ** 7) del b return a if __name__ == '__main__': my_func()
执行代码:
python -m memory_profiler example.py
接收输出:
Line # Mem usage Increment Line Contents ============================================== 3 @profile 4 5.97 MB 0.00 MB def my_func(): 5 13.61 MB 7.64 MB a = [1] * (10 ** 6) 6 166.20 MB 152.59 MB b = [2] * (2 * 10 ** 7) 7 13.61 MB -152.59 MB del b 8 13.61 MB 0.00 MB return a
示例来自上面链接的文档。