roc*_*eys 104 python profiling line-by-line
我一直在使用cProfile来分析我的代码,它一直很好用.我还使用gprof2dot.py来显示结果(使其更清晰).
但是,cProfile(以及到目前为止我见过的大多数其他Python分析器)似乎只在函数调用级别进行分析.当从不同的地方调用某些函数时,这会引起混淆 - 我不知道呼叫#1或呼叫#2是否占用了大部分时间.当所讨论的函数深度为六级时,这会变得更糟,从其他七个地方调用.
如何进行逐行分析?
而不是这个:
function #12, total time: 2.0s
Run Code Online (Sandbox Code Playgroud)
我想看到这样的事情:
function #12 (called from somefile.py:102) 0.5s
function #12 (called from main.py:12) 1.5s
Run Code Online (Sandbox Code Playgroud)
cProfile确实显示了总共有多少时间"转移"到父级,但是当你有一堆层和互连的调用时,这种连接又会丢失.
理想情况下,我希望有一个GUI来解析数据,然后向我显示我的源文件,每个行的总时间.像这样的东西:
main.py:
a = 1 # 0.0s
result = func(a) # 0.4s
c = 1000 # 0.0s
result = func(c) # 5.0s
Run Code Online (Sandbox Code Playgroud)
然后我就可以点击第二个"func(c)"调用来查看该调用中占用的时间,与"func(a)"调用分开.
那有意义吗?是否有任何分析库收集此类信息?我错过了一些很棒的工具吗?
Joe*_*ton 111
我相信这就是Robert Kern的line_profiler的用途.从链接:
File: pystone.py
Function: Proc2 at line 149
Total time: 0.606656 s
Line # Hits Time Per Hit % Time Line Contents
==============================================================
149 @profile
150 def Proc2(IntParIO):
151 50000 82003 1.6 13.5 IntLoc = IntParIO + 10
152 50000 63162 1.3 10.4 while 1:
153 50000 69065 1.4 11.4 if Char1Glob == 'A':
154 50000 66354 1.3 10.9 IntLoc = IntLoc - 1
155 50000 67263 1.3 11.1 IntParIO = IntLoc - IntGlob
156 50000 65494 1.3 10.8 EnumLoc = Ident1
157 50000 68001 1.4 11.2 if EnumLoc == Ident1:
158 50000 63739 1.3 10.5 break
159 50000 61575 1.2 10.1 return IntParIO
Run Code Online (Sandbox Code Playgroud)
希望有所帮助!
小智 40
你也可以使用pprofile(pypi).如果要分析整个执行,则不需要修改源代码.您还可以通过两种方式分析较大程序的子集:
到达代码中的特定点时切换分析,例如:
import pprofile
profiler = pprofile.Profile()
with profiler:
some_code
# Process profile content: generate a cachegrind file and send it to user.
# You can also write the result to the console:
profiler.print_stats()
# Or to a file:
profiler.dump_stats("/tmp/profiler_stats.txt")
Run Code Online (Sandbox Code Playgroud)通过使用统计分析,从调用堆栈异步切换分析(需要一种在所考虑的应用程序中触发此代码的方法,例如信号处理程序或可用的工作线程):
import pprofile
profiler = pprofile.StatisticalProfile()
statistical_profiler_thread = pprofile.StatisticalThread(
profiler=profiler,
)
with statistical_profiler_thread:
sleep(n)
# Likewise, process profile content
Run Code Online (Sandbox Code Playgroud)代码注释输出格式很像行分析器:
$ pprofile --threads 0 demo/threads.py
Command line: ['demo/threads.py']
Total duration: 1.00573s
File: demo/threads.py
File duration: 1.00168s (99.60%)
Line #| Hits| Time| Time per hit| %|Source code
------+----------+-------------+-------------+-------+-----------
1| 2| 3.21865e-05| 1.60933e-05| 0.00%|import threading
2| 1| 5.96046e-06| 5.96046e-06| 0.00%|import time
3| 0| 0| 0| 0.00%|
4| 2| 1.5974e-05| 7.98702e-06| 0.00%|def func():
5| 1| 1.00111| 1.00111| 99.54%| time.sleep(1)
6| 0| 0| 0| 0.00%|
7| 2| 2.00272e-05| 1.00136e-05| 0.00%|def func2():
8| 1| 1.69277e-05| 1.69277e-05| 0.00%| pass
9| 0| 0| 0| 0.00%|
10| 1| 1.81198e-05| 1.81198e-05| 0.00%|t1 = threading.Thread(target=func)
(call)| 1| 0.000610828| 0.000610828| 0.06%|# /usr/lib/python2.7/threading.py:436 __init__
11| 1| 1.52588e-05| 1.52588e-05| 0.00%|t2 = threading.Thread(target=func)
(call)| 1| 0.000438929| 0.000438929| 0.04%|# /usr/lib/python2.7/threading.py:436 __init__
12| 1| 4.79221e-05| 4.79221e-05| 0.00%|t1.start()
(call)| 1| 0.000843048| 0.000843048| 0.08%|# /usr/lib/python2.7/threading.py:485 start
13| 1| 6.48499e-05| 6.48499e-05| 0.01%|t2.start()
(call)| 1| 0.00115609| 0.00115609| 0.11%|# /usr/lib/python2.7/threading.py:485 start
14| 1| 0.000205994| 0.000205994| 0.02%|(func(), func2())
(call)| 1| 1.00112| 1.00112| 99.54%|# demo/threads.py:4 func
(call)| 1| 3.09944e-05| 3.09944e-05| 0.00%|# demo/threads.py:7 func2
15| 1| 7.62939e-05| 7.62939e-05| 0.01%|t1.join()
(call)| 1| 0.000423908| 0.000423908| 0.04%|# /usr/lib/python2.7/threading.py:653 join
16| 1| 5.26905e-05| 5.26905e-05| 0.01%|t2.join()
(call)| 1| 0.000320196| 0.000320196| 0.03%|# /usr/lib/python2.7/threading.py:653 join
Run Code Online (Sandbox Code Playgroud)
请注意,因为pprofile不依赖于代码修改,所以它可以分析顶级模块语句,允许分析程序启动时间(导入模块所需的时间,初始化全局变量......).
它可以生成cachegrind格式的输出,因此您可以使用kcachegrind轻松浏览大型结果.
披露:我是pprofile作者.
为此,您可以借助line_profiler包
1. 1st安装包:
pip install line_profiler
Run Code Online (Sandbox Code Playgroud)
2.使用magic命令将包加载到你的python/notebook环境中
%load_ext line_profiler
Run Code Online (Sandbox Code Playgroud)
3. 如果要分析函数的代码,
请执行以下操作:
%lprun -f demo_func demo_func(arg1, arg2)
Run Code Online (Sandbox Code Playgroud)
如果您按照以下步骤操作,您将获得带有所有详细信息的漂亮格式化输出:)
Line # Hits Time Per Hit % Time Line Contents
1 def demo_func(a,b):
2 1 248.0 248.0 64.8 print(a+b)
3 1 40.0 40.0 10.4 print(a)
4 1 94.0 94.0 24.5 print(a*b)
5 1 1.0 1.0 0.3 return a/b
Run Code Online (Sandbox Code Playgroud)
只是为了改进@Joe Kington 的上述答案。
对于Python 3.x,使用line_profiler:
pip install line_profiler
Run Code Online (Sandbox Code Playgroud)
假设您拥有该程序main.py
并在其中运行,fun_a()
并且fun_b()
您想根据时间进行分析;您将需要@profile
在函数定义之前使用装饰器。例如,
@profile
def fun_a():
#do something
@profile
def fun_b():
#do something more
if __name__ == '__main__':
fun_a()
fun_b()
Run Code Online (Sandbox Code Playgroud)
可以通过执行 shell 命令来分析该程序:
$ kernprof -l -v main.py
Run Code Online (Sandbox Code Playgroud)
可以使用获取参数 $ kernprof -h
Usage: kernprof [-s setupfile] [-o output_file_path] scriptfile [arg] ...
Options:
--version show program's version number and exit
-h, --help show this help message and exit
-l, --line-by-line Use the line-by-line profiler from the line_profiler
module instead of Profile. Implies --builtin.
-b, --builtin Put 'profile' in the builtins. Use 'profile.enable()'
and 'profile.disable()' in your code to turn it on and
off, or '@profile' to decorate a single function, or
'with profile:' to profile a single section of code.
-o OUTFILE, --outfile=OUTFILE
Save stats to <outfile>
-s SETUP, --setup=SETUP
Code to execute before the code to profile
-v, --view View the results of the profile in addition to saving
it.
Run Code Online (Sandbox Code Playgroud)
结果将在控制台上打印为:
Total time: 17.6699 s
File: main.py
Function: fun_a at line 5
Line # Hits Time Per Hit % Time Line Contents
==============================================================
5 @profile
6 def fun_a():
...
Run Code Online (Sandbox Code Playgroud)
编辑:可以使用TAMPPA包解析分析器的结果。使用它,我们可以获得逐行所需的图