Python代码性能分析:cProfile与line_profiler实战指南

Elena
Elena
发布时间:2026-10-14| 5人浏览过
原创

本文详细介绍Python中两种核心性能分析工具:内置的cProfile和第三方的line_profiler。通过具体代码示例,演示如何定位函数级耗时瓶颈及逐行分析执行时间,帮助开发者从宏观到微观优化Python代码性能。

在前一篇文章中,我们探讨了基准测试的概念,通过基准测试可以识别出程序运行变慢的现象。然而,仅发现变慢是不够的,还需要深入探究导致性能下降的具体原因,这就需要进行代码性能分析。Python提供了多种强大的性能分析工具来辅助这一过程。

cProfile

cProfile是Python标准库中默认提供的性能分析器。它的主要功能是测量CPU时间的消耗,并不涉及内存占用或其他与内存相关的指标监控。


from time import sleep
import random


def random_list(start, end, length):
    """
    生成随机列表
    :param start: 随机开始数
    :param end: 随机结束数
    :param length: 列表长度
    """
    data_list = []
    for i in range(length):
        data_list.append(random.randint(start, end))
    return data_list


def bubble_sort(arr):
    """
    冒泡排序: 对列表进行排序
    :param arr 列表
    """
    n = len(arr)
    sleep(1)
    for i in range(n):
        for j in range(0, n - i - 1):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
    return arr


if __name__ == '__main__':
    get_data_list = random_list(1, 99, 10)

    import cProfile
    cProfile.run('bubble_sort({})'.format(get_data_list))

沿用上一篇文章中的示例代码,我们引入cProfile模块来进行分析。下面详细说明其核心方法run()的参数含义。

run(statement, filename=None, sort=-1)

  • statement:指定需要测试执行的代码字符串或函数名称。
  • filename:指定结果输出的文件路径,默认情况下结果会输出到标准输出(stdout)。
  • sort:指定结果排序的方式,常用的排序键包括cumtime(累积时间)、name(函数名)和line(行号)。

为了在统计结果中更清晰地展示耗时部分,我们在示例代码中加入了sleep()调用,运行后的结果如下所示:


❯ python demo.py
         6 function calls in 1.004 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    1.004    1.004 <string>:1(<module>)
        1    0.000    0.000    1.004    1.004 demo.py:19(bubble_sort)
        1    0.000    0.000    1.004    1.004 {built-in method builtins.exec}
        1    0.000    0.000    0.000    0.000 {built-in method builtins.len}
        1    1.004    1.004    1.004    1.004 {built-in method time.sleep}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
  • 结果显示“6 function calls in 1.004 seconds”,表示共有6个函数调用被监控,总耗时为1.004秒。
  • ncalls:表示函数被调用的次数。如果该列显示两个数值,则意味着存在递归调用,其中第二个数值代表原生调用的次数,第一个数值代表总调用次数。
  • tottime:表示函数内部消耗的总时间,不包括调用子函数的时间。这是识别性能瓶颈的关键指标。
  • percall:由tottime除以ncalls计算得出,表示函数每次调用的平均消耗时间。
  • cumtime:表示该函数及其所有子函数执行时间的累计总和。
  • filename:lineno(function):显示被分析函数所在的文件名、行号以及函数名。

line_profiler

line_profiler是一个第三方性能分析工具,它能够提供更细粒度的时间分配信息,即展示程序中每一行代码的具体耗时。当无法确定哪一行语句最耗费资源时,使用此工具非常有效。

由于line_profiler不是Python内置模块,因此需要单独安装。

你可以从GitHub获取源码:https://github.com/pyutils/line_profiler


from time import sleep
import random


def random_list(start, end, length):
    """
    生成随机列表
    :param start: 随机开始数
    :param end: 随机结束数
    :param length: 列表长度
    """
    data_list = []
    for i in range(length):
        data_list.append(random.randint(start, end))
    return data_list


@profile
def bubble_sort(arr):
    """
    冒泡排序: 对列表进行排序
    :param arr 列表
    """
    n = len(arr)
    sleep(1)
    for i in range(n):
        for j in range(0, n - i - 1):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
    return arr


if __name__ == '__main__':
    get_data_list = random_list(1, 99, 10)
    bubble_sort(get_data_list)

在需要监控的目标函数上添加@profile装饰器。安装完成后,通过kernprof命令来运行脚本文件。

该命令的主要参数说明如下:

  • -l:指定使用line_profiler模块进行分析。
  • -v:指定立即将分析结果打印到屏幕输出。

运行上述命令后,得到的结果如下:


kernprof -l -v demo.py
Wrote profile results to demo.py.lprof
Timer unit: 1e-06 s

Total time: 1.00416 s
File: demo.py
Function: bubble_sort at line 18

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
    18                                           @profile
    19                                           def bubble_sort(arr):
    20                                               """
    21                                               冒泡排序: 对列表进行排序
    22                                               :param arr 列表
    23                                               """
    24         1          8.0      8.0      0.0      n = len(arr)
    25         1    1004030.0 1004030.0    100.0      sleep(1)
    26        11         15.0      1.4      0.0      for i in range(n):
    27        55         44.0      0.8      0.0          for j in range(0, n - i - 1):
    28        45         41.0      0.9      0.0              if arr[j] > arr[j + 1]:
    29        20         21.0      1.1      0.0                  arr[j], arr[j + 1] = arr[j + 1], arr[j]
    30         1          1.0      1.0      0.0      return arr

输出结果非常直观,主要包含6列数据。

  • Line #:代码执行的行号。
  • Hits:该行代码被执行的次数。
  • Time:该行代码的执行时间,单位通常为微秒。
  • Per Hit:即Time除以Hits,表示每次执行该行的平均时间。
  • % Time:该行代码总执行时间占整个函数执行时间的百分比。
  • Line Contents:具体的代码行内容。

只需关注% Time这一列,即可清晰地识别出哪些代码行消耗了最多的时间,从而进行针对性优化。

总结

性能测试分析在项目管理层面是一个庞大的课题。对于测试工程师而言,重点通常在于性能工具的使用以及从用户视角评估系统性能[1];而对于开发工程师来说,每个功能模块都是由一个个函数或方法构成的。因此,深入分析每个函数甚至每行代码的耗时情况,是实现代码层面性能优化的关键步骤。

以上就是关于Python代码性能分析的详细内容,更多关于Python代码性能分析的资料,请关注本站发布的其他相关文章。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。