如何使用cProfile来分析Python代码

Python的cProfile模块能收集程序执行时间的统计信息,帮助找到性能瓶颈。通过修改cProfile报告的排序方式,可以专注于最耗时的部分。cProfile结果可以用于优化代码,比如减少频繁的函数调用或优化长执行时间的函数。导出的数据可以使用第三方工具如pyprof2calltree或SnakeViz进一步分析。除了cProfile,还有其他分析工具如PyCharm的Profiler和line_profiler提供不同的分析视角。
摘要由CSDN通过智能技术生成

Python可能不是最快的语言,但是它通常足够快。 当程序员的时间比CPU时间更重要时,Python是理想的选择。

就是说,如果给定的Python应用程序很落后,那么您就没有义务仅仅吸收它。 Python解释器的基本安装附带的工具可以为您提供有关程序哪些部分运行缓慢的详细反馈,并提供有关如何加快它们的一些提示。

[InfoWorld的要点: 开始使用Anaconda,这是数据科学的Python发行版 Python的Anaconda发行版中的新增功能 5个用于数据科学的基本Python工具-现已改进 | 通过InfoWorld的App Dev Report新闻通讯了解编程方面的热门话题。 ]

如何使用cProfile

cProfile模块收集有关Python程序执行时间的统计信息。 它可以报告从整个应用程序到单个语句或表达式的所有内容。

这是一个如何使用cProfile的玩具示例:

def add(x,y):
    x+=str(y)
    return x

def add_2(x,y):
    if y % 20000 == 0:
        z=[]
        for q in range(0,400000):
            z.append(q)

def main():
    a=[]
    for n in range(0,200000):
        add(a,n)
        add_2(a,n)
        
if __name__ == '__main__':
    import cProfile
    cProfile.run('main()')

此示例运行应用程序的main()函数,并分析main()main()调用的所有内容的性能。 也可以仅分析程序的一部分 ,但是对于初学者来说,最常见的用途是分析整个程序。

运行上面的示例,您将收到类似以下输出的内容:

cprofile 01 IDG

此处显示的是程序进行的所有函数调用的列表,以及有关每个函数的统计信息:

  • 在顶部(蓝色的第一行)中,我们看到了配置文件程序中的调用总数和总执行时间。 您可能还会看到“原始调用”的数字,表示非递归调用,或直接对函数进行的调用,这些调用又不会在调用堆栈中进一步调用自身。
  • ncalls :拨打的电话数。 如果看到两个数字用斜杠分隔,则第二个数字是该函数的原始调用数。
  • tottime :在该函数中花费的总时间, 包括对其他函数的调用。
  • percall:每次通话的平均时间为tottime,通过采取tottimencalls除以得到。
  • cumtime :在该函数上花费的总时间,包括对其他函数的调用。
  • percall (#2):每次通话的平均时间为cumtimecumtime除以ncalls )。
  • filename:lineno:相关调用的文件名,行号和函数名。

如何修改cProfile报告

默认情况下, cProfile按“标准名称”对输出进行排序,这意味着它按最右列中的文本(文件名,行号等)进行排序。

如果希望每个功能调用的自上而下的常规报告供参考,则默认格式很有用。 但是,如果您试图解决瓶颈问题,则可能需要首先列出程序中最耗时的部分。

我们可以通过稍微不同地调用cProfile来产生这些结果。 请注意,如何重新ncalls上述程序的底部,以按不同的列对统计信息进行排序(在本例中为ncalls ):

if __name__ == '__main__':
    import cProfile, pstats
    profiler = cProfile.Profile()
    profiler.enable()
    main()
    profiler.disable()
    stats = pstats.Stats(profiler).sort_stats('ncalls')
    stats.print_stats()

结果将如下所示:

cprofile 02 IDG

这是所有工作的原理:

  • 我们不是通过不太灵活的cProfile.run()执行命令,而是创建了一个分析对象 profiler
  • 当我们想要分析某些动作时,我们首先在事件探查器对象实例上调用.enable() ,然后运行该动作,然后调用.disable() 。 (这是仅分析程序一部分的一种方法。)
  • pstats模块用于处理探查器对象收集的结果并打印这些结果。

将事件探查器对象和pstats结合使用,使我们能够处理捕获的概要文件数据-例如,对生成的统计数据进行不同的排序。 在此示例中,使用.sort_stats('ncalls')通过ncalls列对统计信息进行排序。 其他排序选项可用。

如何使用cProfile结果进行优化

cProfile输出可用的排序选项使我们可以找出程序中潜在的性能瓶颈。

ncalls

您可以使用cProfile挖掘的第一个也是最重要的信息是,通过ncalls列可以最频繁地调用哪些函数。

在Python中,仅进行函数调用的行为会导致相对大量的开销。 如果某个函数在紧密循环中反复调用,即使它不是长时间运行的函数,也可以保证会影响性能。

在上面的示例中,函数add (和函数add_2 )被循环调用。 将循环移到add函数本身中,或完全内联add函数将解决此问题。

tottime

另一个有用的统计细节,可以通过tottime列来花费程序的大部分时间执行功能。

在上面的示例中, add_2函数使用循环来模拟一些昂贵的计算,这会将其tottime得分推高了。 具有较高tottime得分的任何函数都应仔细观察,尤其是在多次调用或紧密循环调用时。

请注意,您始终需要考虑使用该函数的上下文 。 如果某个函数的使用时间tottime但是仅被调用一次(例如,仅在程序启动时),则它不太可能成为瓶颈。 但是,如果您要减少启动时间,则需要知道启动时调用的函数是否正在使其他所有内容等待。

如何导出cProfile数据

如果要以更高级的方式使用cProfile生成的统计信息,可以将其导出到数据文件中:

stats = pstats.Stats(profiler)
stats.dump_stats('/path/to/stats_file.dat')

此文件可在使用读回pstats模块,然后进行排序或显示pstats 。 数据也可以被其他程序重复使用。 两个例子:

  • pyprof2calltree从配置文件数据呈现程序的调用图和使用情况统计的详细可视化。 本文提供了其用法的详细实际示例。
  • snakeviz还从cProfile数据生成可视化cProfile ,但对数据使用不同的表示形式-“旭日”而不是pyprof2calltree的“ flame”图。

超越cProfile进行Python分析

cProfile几乎不是剖析Python应用程序的唯一方法。 cProfile与Python捆绑在一起,无疑是最方便的方法之一。 但其他人值得关注。

一个项目py-spy通过采样其调用活动来构建Python应用程序的配置文件。 py-spy可用于检查正在运行的Python应用程序,而无需停止和重新启动它,而无需更改其代码库,因此可用于分析已部署的应用程序。 py-spy还会生成一些有关Python运行时产生的开销(例如,垃圾回收开销)的统计信息,而cProfile不会。

From: https://www.infoworld.com/article/3329750/how-to-profile-python-code.html

参考资源链接:[Python性能分析使用Profile工具定位瓶颈](https://wenku.csdn.net/doc/5rnd2s3jpi?utm_source=wenku_answer2doc_content) 在进行Python代码性能优化时,确定性能瓶颈至关重要。为此,我们推荐参考《Python性能分析使用Profile工具定位瓶颈》这本书,它详细介绍了如何运用profile模块进行性能分析。 cProfilePython的一个内置性能分析工具,相较于profile,它提供了更详细的调用统计信息,且不会对程序性能产生太大影响。以下是使用cProfile进行性能分析的步骤和方法: 1. 首先,确保你已经安装了Python环境,并且了解如何在你的系统上运行Python脚本。 2. 导入cProfile模块,并在需要分析代码块前启动分析器,代码执行完毕后再停止分析器。例如,要分析函数`foo()`的性能,可以使用以下代码: ```python import cProfile def foo(): # 你的函数代码 pass cProfile.run('foo()') ``` 3. 运行上述代码后,cProfile将输出各函数的调用次数、总时间、平均时间以及累计时间等信息。输出信息会按照累计时间排序,以帮助你快速识别出性能瓶颈。 4. 通过分析输出,你可以看到各个函数的性能情况,比如哪个函数的调用次数最多,哪个函数消耗的时间最长。 5. 一旦识别出性能瓶颈,你可以使用Python的其他优化技术,如减少函数调用开销、使用更高效的算法、优化数据结构等,来改进代码。 6. 你可以通过编写脚本来自动化分析过程,或者使用cProfile模块的命令行工具来分析脚本文件。 7. 最后,为了深入理解cProfile的工作原理和更多高级用法,建议深入阅读《Python性能分析使用Profile工具定位瓶颈》一书。 通过以上步骤,你将能够有效地使用cProfile进行性能分析,识别并解决Python代码中的性能瓶颈,从而提高你的代码效率和质量。 参考资源链接:[Python性能分析使用Profile工具定位瓶颈](https://wenku.csdn.net/doc/5rnd2s3jpi?utm_source=wenku_answer2doc_content)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值