tracemalloc:无法捕获更高的帧

tracemalloc: cannot capture higher frames

我正在尝试使用 tracemalloc 提取代码帧来找出大型项目中的内存泄漏。但是,我无法获得超过一个最深的框架,这对于具有大量依赖项和无数嵌套调用的大型项目是无用的。根据the docs,我尝试使用:

  1. tracemalloc.start 限制参数
  2. PYTHONTRACEMALLOC 环境变量
  3. -X tracemalloc 命令行参数

tracemalloc.get_traceback_limit() 显示我设置的正确数字。但是,我仍然只得到每个 Traceback 对象的一帧。它在不同机器上的 Python 版本 3.8.5 和 3.9.7 上工作相同。这里有什么问题??我该如何解决这个问题?

这是最小的例子:

import os
import tracemalloc

def get_top_malloc(trace_number):
    snapshot = tracemalloc.take_snapshot()
    snapshot = snapshot.filter_traces((
        tracemalloc.Filter(False, "<frozen importlib._bootstrap>"),
        tracemalloc.Filter(False, "<unknown>"),
    ))
    top_stats = snapshot.statistics("lineno")
    msg = []
    if trace_number > 0:
        msg.append(f"Top malloc {trace_number} lines")
        for index, stat in enumerate(top_stats[:trace_number]):
            msg.append(f"#{index}: {stat.size // 1024} KB, {stat.count} times")
            print(stat.traceback._frames)  # Only single frame is here!
            print(dir(stat.traceback))
            msg.extend(line for line in stat.traceback.format(limit=16))
        other = top_stats[trace_number:]
        if other:
            size = sum(stat.size for stat in other)
            msg.append(f"{len(other)} other: {size // 1024} KB")
    total = sum(stat.size for stat in top_stats)
    msg.append(f"Total allocated size: {total // 1024 // 1024} MB")
    return "\n".join(msg)


storage = {}

def func2():
    def func3():
        value = '3.1415926535897932384626433832795028841971'
        value = value * 4096
        storage['pi'] = value
    func3()

def func1():
    func2()

if __name__ == "__main__":
    tracemalloc.start(4)
    print(f"\n-- Limit: {tracemalloc.get_traceback_limit()}")
    func1()
    print(f"\n-- {get_top_malloc(1)}")
    tracemalloc.stop()

我找到了解决方案,它很简单但并不明显。快照对象的 statistics(...) 方法采用 key_type 参数,该参数用于按文件 ("filename")、文件+行 ("lineno") 或按整个追溯("traceback")。我使用默认值 "lineno" 过滤掉每个回溯的最后一帧除外的所有内容,因此切换到 "traceback" 选项解决了问题并允许我获得我需要的所有帧 :)