PyPDF2合并PDF输出为空的主因是未调用write()或PdfWriter未正确添加页面;新版需用PdfReader.pages逐页add_page,并以"wb"模式调用write()。

PyPDF2合并PDF时为什么输出文件是空的
常见原因是没调用 write() 方法,或者 PdfWriter(PyPDF2 3.0+)对象没正确添加页面。PyPDF2 2.x 用 PdfFileMerger 或 PdfFileWriter,3.x 起统一为 PdfWriter 和 PdfReader,旧写法会静默失败。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 确认 PyPDF2 版本:
pip show PyPDF2;若 ≥3.0,必须用PdfReader读取、PdfWriter写入 - 每读一个 PDF,都要用
reader.pages获取页面列表,再逐页writer.add_page(page) - 别漏掉
with open(..., "wb") as f: writer.write(f)—— 缺少"wb"模式或没write()就生成空文件 - 避免直接
writer.add_page(reader.getPage(0))(已废弃),新版必须用reader.pages[i]
按文件名顺序合并合同PDF的可靠做法
操作系统返回的 os.listdir() 或 glob.glob() 不保证顺序,合同常需按“合同A_v1.pdf”“合同A_v2.pdf”等逻辑排序,否则合并后页序错乱。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 用
sorted(glob.glob("*.pdf"), key=natural_sort_key),其中natural_sort_key对数字部分做 int 转换(如把"v10"排在"v2"后) - 不要依赖创建时间(
os.path.getctime)—— Windows 和 macOS 行为不一致,且用户可能复制粘贴修改过时间 - 如果合同有固定前缀(如
"contract_2024_*.pdf"),优先用glob.glob("contract_2024_*.pdf")精确匹配,再排序 - 合并前打印文件名列表:
print([os.path.basename(f) for f in pdf_files]),人工核对顺序
合并含中文书签或表单域的PDF会丢失内容
PyPDF2 本身不保留书签(outline)、表单域(AcroForm)、注释(annotations)和某些元数据。合同若有签字栏、下拉选项或章节跳转书签,直接合并后这些交互元素全部消失,只剩静态页面。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 纯文本+图片类合同:PyPDF2 安全可用;含交互元素的合同,改用
pypdf(PyPDF2 的继任者,支持书签复制)或fitz(PyMuPDF) - 若坚持用 PyPDF2,可先用
pdfcpu attach或 Adobe Acrobat 手动预处理,把表单“压平”成图像再合并 - 检查合并后文件大小是否异常小——可能是部分页面因加密/权限问题被跳过,加
try/except包裹PdfReader初始化,并打印警告
大合同批量合并时内存爆满或卡死
一次性读取几十个百兆 PDF,每个 PdfReader 实例都会缓存全部页面对象,极易触发 MemoryError,尤其在低配服务器上。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 用生成器逐个处理:
for pdf_path in pdf_files:→ 创建PdfReader→ 添加页面 →del reader→gc.collect() - 避免把所有
PdfReader实例存在列表里:readers = [PdfReader(f) for f in files]是高危写法 - 合并超 50 个文件时,考虑分批写入临时文件,再两两合并(减少峰值内存)
- 用
psutil.Process().memory_info().rss在循环中打点监控,及时发现泄漏



















