如何逐行分析 Python 代码?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3927628/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 13:22:58  来源:igfitidea点击:

How can I profile Python code line-by-line?

pythonprofilingline-by-line

提问by rocketmonkeys

I've been using cProfile to profile my code, and it's been working great. I also use gprof2dot.pyto visualize the results (makes it a little clearer).

我一直在使用 cProfile 来分析我的代码,而且效果很好。我还使用gprof2dot.py来可视化结果(使它更清晰一点)。

However, cProfile (and most other Python profilers I've seen so far) seem to only profile at the function-call level. This causes confusion when certain functions are called from different places - I have no idea if call #1 or call #2 is taking up the majority of the time. This gets even worse when the function in question is six levels deep, called from seven other places.

但是,cProfile(以及我目前见过的大多数其他 Python 分析器)似乎只在函数调用级别进行分析。当从不同的地方调用某些函数时,这会导致混乱 - 我不知道调用 #1 还是调用 #2 占用了大部分时间。当所讨论的函数有六层深,从其他七个地方调用时,情况会变得更糟。

How do I get a line-by-line profiling?

如何获得逐行分析?

Instead of this:

取而代之的是:

function #12, total time: 2.0s

I'd like to see something like this:

我想看到这样的事情:

function #12 (called from somefile.py:102) 0.5s
function #12 (called from main.py:12) 1.5s

cProfile does show how much of the total time "transfers" to the parent, but again this connection is lost when you have a bunch of layers and interconnected calls.

cProfile 确实显示了“传输”到父级的总时间有多少,但是当您有一堆层和互连调用时,此连接再次丢失。

Ideally, I'd love to have a GUI that would parse through the data, then show me my source file with a total time given to each line. Something like this:

理想情况下,我希望有一个可以解析数据的 GUI,然后向我展示我的源文件,并为每一行提供总时间。像这样的东西:

main.py:

a = 1 # 0.0s
result = func(a) # 0.4s
c = 1000 # 0.0s
result = func(c) # 5.0s

Then I'd be able to click on the second "func(c)" call to see what's taking up time in that call, separate from the "func(a)" call.

然后我就可以点击第二个“func(c)”调用来查看该调用中占用的时间,与“func(a)”调用分开。

Does that make sense? Is there any profiling library that collects this type of information? Is there some awesome tool I've missed?

那有意义吗?是否有收集此类信息的分析库?有没有我错过的很棒的工具?

采纳答案by Joe Kington

I believe that's what Robert Kern's line_profileris intended for. From the link:

我相信这就是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

Hope that helps!

希望有帮助!

回答by vpelletier

You could also use pprofile(pypi). If you want to profile the entire execution, it does not require source code modification. You can also profile a subset of a larger program in two ways:

您也可以使用pprofile( pypi)。如果要分析整个执行过程,则不需要修改源代码。您还可以通过两种方式分析较大程序的子集:

  • toggle profiling when reaching a specific point in the code, such as:

    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")
    
  • toggle profiling asynchronously from call stack (requires a way to trigger this code in considered application, for example a signal handler or an available worker thread) by using statistical profiling:

    import pprofile
    profiler = pprofile.StatisticalProfile()
    statistical_profiler_thread = pprofile.StatisticalThread(
        profiler=profiler,
    )
    with statistical_profiler_thread:
        sleep(n)
    # Likewise, process profile content
    
  • 到达代码中的特定点时切换分析,例如:

    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")
    
  • 通过使用统计分析从调用堆栈异步切换分析(需要一种在考虑的应用程序中触发此代码的方法,例如信号处理程序或可用的工作线程):

    import pprofile
    profiler = pprofile.StatisticalProfile()
    statistical_profiler_thread = pprofile.StatisticalThread(
        profiler=profiler,
    )
    with statistical_profiler_thread:
        sleep(n)
    # Likewise, process profile content
    

Code annotation output format is much like line profiler:

代码注释输出格式很像行分析器:

$ 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

Note that because pprofile does not rely on code modification it can profile top-level module statements, allowing to profile program startup time (how long it takes to import modules, initialise globals, ...).

请注意,因为 pprofile 不依赖于代码修改,它可以分析顶级模块语句,允许分析程序启动时间(导入模块、初始化全局变量需要多长时间,...)。

It can generate cachegrind-formatted output, so you can use kcachegrindto browse large results easily.

它可以生成 cachegrind 格式的输出,因此您可以使用kcachegrind轻松浏览大型结果。

Disclosure: I am pprofile author.

披露:我是 pprofile 作者。

回答by Fabio Zadrozny

PyVmMonitor has a live-view which can help you there (you can connect to a running program and get statistics from it).

PyVmMonitor 有一个实时视图,可以在那里帮助您(您可以连接到正在运行的程序并从中获取统计信息)。

See: http://www.pyvmmonitor.com/

见:http: //www.pyvmmonitor.com/

回答by Sateesh

You can take help of line_profilerpackage for this

为此,您可以借助line_profiler

1. 1st install the package:

1. 1st安装包:

    pip install line_profiler

2. Use magic command to load the package to your python/notebook environment

2.使用magic命令将包加载到你的python/notebook环境中

    %load_ext line_profiler

3. If you want to profile the codes for a function then
do as follows:

3. 如果要分析函数的代码,
请执行以下操作:

    %lprun -f demo_func demo_func(arg1, arg2)

you will get a nice formatted output with all the details if you follow these steps :)

如果您按照以下步骤操作,您将获得带有所有详细信息的漂亮格式化输出:)

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