Python内存泄漏测试用Pytest-Memprof吗

wen python案例 23

本文目录导读:

Python内存泄漏测试用Pytest-Memprof吗

  1. pytest-memprof 的优缺点
  2. 推荐方案
  3. 实际测试框架示例
  4. 专业工具

对于Python内存泄漏测试,pytest-memprof 是一个可选方案,但我更推荐组合使用 pytest + tracemallocmemory_profiler,不过让我先分析一下 pytest-memprof 的适用性。

pytest-memprof 的优缺点

优点

  • 专门为 pytest 设计
  • 装饰器语法简洁
  • 可以基于使用量设定阈值

缺点

  • 项目维护不活跃(最后更新较久)
  • 功能相对基础
  • 不如 tracemalloc 精细

推荐方案

方案1:pytest + tracemalloc(最推荐)

Python 3.4+ 内置,无需额外安装:

import tracemalloc
def test_memory_leak():
    tracemalloc.start()
    # 记录初始快照
    snapshot1 = tracemalloc.take_snapshot()
    # 执行可能泄漏的操作
    for _ in range(1000):
        data = create_large_object()
        # 忘记释放...
    # 记录结束快照
    snapshot2 = tracemalloc.take_snapshot()
    # 比较差异
    stats = snapshot2.compare_to(snapshot1, 'lineno')
    # 断言内存增长在合理范围内
    total_growth = sum(stat.size_diff for stat in stats)
    assert total_growth < 10 * 1024 * 1024  # 小于10MB

方案2:pytest + memory_profiler

from memory_profiler import profile
@profile
def test_function():
    # 测试代码
    result = []
    for i in range(10000):
        result.append('x' * 1000)
    return result
def test_memory():
    # 使用 mprof 命令行工具
    # mprof run pytest test.py
    # mprof plot
    pass

方案3:自定义 pytest fixture + tracemalloc

import pytest
import tracemalloc
@pytest.fixture
def memory_check():
    tracemalloc.start()
    yield
    current, peak = tracemalloc.get_traced_memory()
    tracemalloc.stop()
    # 报告内存使用
    print(f"Current: {current / 1024 / 1024:.2f} MB")
    print(f"Peak: {peak / 1024 / 1024:.2f} MB")
def test_with_leak(memory_check):
    leaker = LeakyClass()
    for _ in range(1000):
        leaker.leak()

实际测试框架示例

完整的测试框架:

# conftest.py
import pytest
import tracemalloc
import gc
@pytest.fixture(autouse=True)
def memory_leak_check():
    """自动检查每个测试的内存泄漏"""
    tracemalloc.start()
    gc.collect()  # 清理垃圾
    snapshot_before = tracemalloc.take_snapshot()
    yield
    gc.collect()  # 强制垃圾回收
    snapshot_after = tracemalloc.take_snapshot()
    # 过滤掉内部调用
    stats = snapshot_after.compare_to(snapshot_before, 'lineno')
    stats = [s for s in stats if not s.traceback[0].filename.startswith('<')]
    significant_leaks = [s for s in stats if s.size_diff > 1024]  # > 1KB
    if significant_leaks:
        print("\n内存泄漏检测结果:")
        for stat in significant_leaks[:5]:  # 显示前5个
            print(stat)
# test_memory.py
def test_no_leak():
    """正常测试"""
    data = [1, 2, 3]
    assert sum(data) == 6
def test_potential_leak():
    """可能泄漏的测试"""
    class Leak:
        def __init__(self):
            self.data = [0] * 1000000
    # 会创建大量对象但不释放
    for _ in range(100):
        l = Leak()

专业工具

对于生产环境,推荐:

  1. pytest-leaks:专门的内存泄漏测试插件

    pip install pytest-leaks
    pytest --leaks test.py
  2. objgraph:查看对象引用图

    import objgraph
    def test_reference_cycles():
        # 检测循环引用
        objgraph.show_most_common_types(limit=10)

不建议单独使用 pytest-memprof,因为:

  • 功能局限且维护少
  • 不如内置 tracemalloc 灵活

推荐组合:

  • 日常测试:pytest + tracemalloc(内置)
  • 详细分析:pytest + memory_profiler
  • CI/CD集成:pytest-leaks 或自定义 fixture

选择最适合你项目的工具组合即可。

抱歉,评论功能暂时关闭!