Python 3.11 不自动压缩办公脚本内存,关键在于优化 pandas/openpyxl 等库的使用:分块读取、显式指定列、控制 dtype、避免 openpyxl 全量加载、及时 close 工作簿、慎用 category 类型。

Python 3.11 本身不自动压缩办公脚本的内存,真正起效的是你对 pandas、openpyxl、xlrd(已弃用)等库的使用方式——尤其是读取、转换和丢弃数据的时机。
读 Excel 时别用 pandas.read_excel() 全量加载
默认行为会把整张表转成 DataFrame,哪怕你只改一列;内存峰值常是原始文件大小的 3–5 倍。
- 用
chunksize=1000分块读:适合做清洗或逐块写入新表 - 用
usecols显式指定列名或列索引,比如usecols=["A", "C", "E"]或usecols=[0, 2, 4],跳过无用字段 - 用
dtype控制列类型:"status": "category"比object节省 80%+ 内存;数值列优先设为np.int32或np.float32 - 避免
read_excel(..., engine="openpyxl")读大文件——它要加载整个 XML 结构树;换成engine="odf"(小文件)或直接用pyxlsb(.xlsb 格式)更轻量
openpyxl 加载工作簿后记得调用 workbook.close()
很多人以为 del workbook 就释放了,其实 openpyxl 内部用了大量弱引用和缓存,不显式 .close(),底层文件句柄和 XML 解析器可能一直挂着。
- 务必在
with块里操作:with openpyxl.load_workbook(path) as wb: - 如果必须手动管理,
wb.close()后再del wb,否则gc.collect()也清不掉 - 不要反复
load_workbook→save→load_workbook:每次都会新建解析上下文;改完直接save,别 reload
字符串列是内存黑洞,astype("category") 不是万能解
当 Excel 中有大量重复文本(如部门名、状态码、城市名),object 类型会让 pandas 为每个值存一份独立字符串对象;category 可映射为整数编码,但仅在重复率 >10% 时才划算。
立即学习“Python免费学习笔记(深入)”;
- 先检查唯一值比例:
df["dept"].nunique() / len(df), - 转之前用
.str.strip().str.upper()统一格式,否则空格或大小写差异会导致“相同值”被当成不同类别 - 避免对含
NaN的列直接astype("category")——它会把NaN当作一个额外类别,反而增重;先fillna("MISSING")再转 - 导出前记得
df.select_dtypes("category").apply(lambda x: x.astype(str)),否则to_excel可能报错或写入乱码
用 del + gc.collect() 清理中间变量,但别迷信 gc.collect()
Python 3.11 的 GC 策略没变,只是内存报告更准了——你看到 RSS 没降,大概率是还有活引用,不是 GC 失效。
- 显式
del df_raw, temp_merge, unused_sheet,尤其在循环处理多个文件时 - 紧接
gc.collect(),但只在确认所有引用已删且内存确实卡住时才加(频繁调用反而拖慢) - 检查是否意外保留了引用:比如把某个
DataFrame存进了全局list、闭包或 logging handler 里 - 用
sys.getsizeof(df)看表头开销,用df.memory_usage(deep=True).sum()看真实数据内存——前者常是后者的 1/100,别被误导
最常被忽略的一点:办公脚本里大量 pd.concat([df1, df2, df3]) 和 df.copy() 是静默内存放大器。它们不警告、不报错,只在你打开任务管理器时突然现身。控制住读取粒度和中间态生命周期,比升级 Python 版本管用十倍。


















