如何逐行分析 Python 代码?

2025-02-27 09:06:00
admin
原创
179
摘要:问题描述:我一直在使用 cProfile 来分析我的代码,效果非常好。我还使用gprof2dot.py来可视化结果(使其更清晰一些)。但是,cProfile(以及我迄今为止见过的大多数其他 Python 分析器)似乎只在函数调用级别进行分析。当某些函数从不同位置调用时,这会引起混淆 - 我不知道调用 #1 还...

问题描述:

我一直在使用 cProfile 来分析我的代码,效果非常好。我还使用gprof2dot.py来可视化结果(使其更清晰一些)。

但是,cProfile(以及我迄今为止见过的大多数其他 Python 分析器)似乎只在函数调用级别进行分析。当某些函数从不同位置调用时,这会引起混淆 - 我不知道调用 #1 还是调用 #2 占用了大部分时间。当所讨论的函数深度为六级,从其他七个位置调用时,情况会变得更糟。

如何获得逐行分析的结果?

而不是这样:

function #12, total time: 2.0s

我希望看到这样的内容:

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

cProfile 确实显示了总时间中有多少“转移”到父级,但是当您拥有一堆层和相互连接的调用时,这种连接就会丢失。

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

main.py:

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

然后,我可以单击第二个“func(c)”调用来查看该调用中占用时间的内容,与“func(a)”调用分开。这有意义吗?


解决方案 1:

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

解决方案 2:

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

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

代码注释的输出格式与线路分析器非常相似:

$ 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

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

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

披露:我是 pprofile 的作者。

解决方案 3:

只是为了改进@Joe Kington 的上述答案。

对于Python 3.x,使用line_profiler


安装:

pip install line_profiler

用法:

假设您有一个程序main.py,其中有函数,fun_a()并且fun_b()您想要根据时间进行分析;您需要@profile在函数定义之前使用装饰器。例如,

from line_profiler import profile

@profile
def fun_a():
    #do something

@profile
def fun_b():
    #do something more

if __name__ == '__main__':
    fun_a()
    fun_b()

可以通过执行 shell 命令来分析该程序:

$ kernprof -l -v main.py

可以使用以下方式获取参数$ 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.

结果将会打印在控制台上:

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():
...


编辑:可以使用TAMPPA包解析剖析器的结果。使用它,我们可以逐行获得所需的图,如下所示
阴谋

解决方案 4:

您可以借助line_profiler包来实现这一点

1.首先安装包:

    pip install line_profiler

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

    %load_ext line_profiler

**3.如果您想要分析某个函数的代码,请

执行以下操作:**

    %lprun -f demo_func demo_func(arg1, arg2)

如果你按照以下步骤操作,你将获得一个格式良好、包含所有详细信息的输出:)

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

解决方案 5:

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

请参阅:http://www.pyvmmonitor.com/

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3018  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1880  
  PLM(产品生命周期管理)系统在企业产品研发、生产与管理过程中发挥着至关重要的作用。它能够整合产品全生命周期中的各类数据与流程,提升企业的协同效率、降低成本并加速产品上市。然而,不同企业由于业务模式、产品特性以及管理理念的差异,对PLM系统有着个性化的需求。如何实现这些个性化需求,成为企业在实施PLM系统定制开发时面临...
免费plm软件   0  
  在企业的发展进程中,跨地域协同工作变得愈发普遍和重要。不同地区的团队需要紧密合作,以实现资源共享、提高效率和创新能力。而产品生命周期管理(PLM)系统在这一过程中发挥着关键作用,尤其是其分布式架构,为跨地域协同提供了强大的支持。PLM系统概述PLM系统是一种用于管理产品从概念设计到退役全生命周期过程中所有数据和流程的软...
免费plm管理软件   0  
  在企业项目管理中,资源平衡是确保项目顺利推进、提高效率与效益的关键环节。产品生命周期管理(PLM)系统作为整合产品全生命周期信息与流程的重要工具,为实现资源平衡提供了强大的支持。通过合理运用PLM系统,企业能够优化资源分配、提升协同效率,从而在激烈的市场竞争中占据优势。接下来,我们将深入探讨如何借助PLM系统实现资源平...
plm系统   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用