from pypdf import PdfWriter, PdfReader
w = PdfWriter()
for p in files:
    w.append(p)
w.write("out.pdf"); w.close()

月底合并 300 份对账单,每个 8MB 左右,进程 RSS 一路涨到 4.2GB,K8s 里直接 OOMKilled,退出码 137。单份合并没问题,份数一多就崩。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。

原因不复杂,PdfMerger 把每份文档的对象树都读进内存再写,300 份叠起来远超容器 limit。中间对象没有及时释放,Python 的引用计数要等函数返回才降。容器 limit 设的是 1GB,峰值一碰就杀。

「pypdf 合并内存」确认了原因之后,改动尽量只碰那一处,顺手改的东西后面最容易出问题。改完隔一天再看一次,当场正常不代表能稳住。

测试环境和线上的差别,往往就在版本号和那几行被忽略的配置上。线上出问题先对时间点,跟发布、备份、任务执行的时刻排一排,能省掉一半功夫。

处理上按这个顺序:改用 append 追加到同一个 writer 避免中间对象堆积;每份处理完关闭 reader 及时释放句柄;限制单次合并份数 超过就分批落盘再合并;容器内存 limit 提到峰值以上并留出余量。

改完只确认一件事:同样 300 份文件合并完成,峰值 RSS 稳定在 700MB 以下,容器没有重启记录。

作者 9823189