
本文介绍一种可靠方法,通过遍历当前作用域中的变量并结合类型判断与属性检查,精准定位所有活跃的 polars dataframe 实例,并支持按内存占用排序分析。
本文介绍一种可靠方法,通过遍历当前作用域中的变量并结合类型判断与属性检查,精准定位所有活跃的 polars dataframe 实例,并支持按内存占用排序分析。
在从 Pandas 迁移至 Polars 的过程中,内存优化成为关键环节。与 Pandas 不同,Polars DataFrame 的实际内存占用不能通过 sys.getsizeof() 准确获取——该函数仅返回 Python 对象头的浅层大小,而 Polars 数据实际存储在 Rust 堆中。正确方式是调用 .estimated_size() 方法(返回字节级近似值),但前提是必须先识别出哪些变量是 Polars DataFrame。
遗憾的是,locals().items() 本身不会遗漏 Polars DataFrame;你未看到它们,通常是因为:
- 变量作用域问题(如定义在函数内、类中或模块级但未在当前
locals()范围); - 变量名被覆盖或已
del删除; - 对象被包装在列表、字典等容器中,未直接暴露为顶层变量。
因此,主动类型+属性双重校验是更健壮的策略:
import sys
import polars as pl
def sizeof_fmt(num, suffix='B'):
for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']:
if abs(num) < 1024.0:
return f"{num:3.1f} {unit}{suffix}"
num /= 1024.0
return f"{num:.1f} Yi{suffix}"
def find_polars_dataframes(scope_dict=None):
"""
在指定命名空间(默认为当前 locals())中查找所有 Polars DataFrame 实例。
使用 isinstance(value, pl.DataFrame) + hasattr(value, 'estimated_size') 双重验证,
避免误判继承类或不完整对象。
"""
if scope_dict is None:
scope_dict = locals()
results = []
for name, value in scope_dict.items():
if isinstance(value, pl.DataFrame):
try:
# 确保 estimated_size 可调用且返回合理数值
size = value.estimated_size()
if isinstance(size, int) and size >= 0:
results.append((name, size))
except (AttributeError, RuntimeError, ValueError):
# 忽略无法估算大小的异常情况(如空帧、未初始化状态)
pass
return results
# ✅ 正确用法:显式传入 locals()(注意:必须在目标作用域内调用!)
polars_dfs = find_polars_dataframes(locals())
# 合并 Polars(用 estimated_size)和普通对象(用 sys.getsizeof)
all_objects = [
*[(name, size) for name, size in polars_dfs],
*[(name, sys.getsizeof(value))
for name, value in locals().items()
if not isinstance(value, pl.DataFrame)]
]
# 按大小降序取 Top 10
for name, size in sorted(all_objects, key=lambda x: -x[1])[:10]:
print(f"{name:>30}: {sizeof_fmt(size):>8}")⚠️ 重要注意事项:
立即学习“Python免费学习笔记(深入)”;
-
find_polars_dataframes()必须在目标变量所在的作用域中调用(例如,若 DataFrame 定义在函数load_data()内,则需在该函数末尾调用,而非全局作用域); - 若需跨作用域扫描(如检查所有模块级变量),可改用
globals()或结合gc.get_objects()(但性能较低,且需过滤pl.DataFrame类型); -
estimated_size()是近似值(基于列数据类型的位宽与长度计算),不包含临时计算缓存,但对内存诊断已足够可靠; - 对于嵌套结构(如
dict['df']或list[0]),需递归遍历容器——基础版不覆盖此场景,建议配合dill或自定义遍历器扩展。
总结:识别 Polars DataFrame 的核心是类型安全检测 + Rust 内存接口调用,而非依赖通用内存函数。将上述逻辑封装为调试工具函数,可显著提升 Polars 项目中的内存可观测性与优化效率。


















