python-docx无法直接生成pdf,需借助word(windows用win32com)或libreoffice(跨平台)等外部工具实现转换,二者各有适用场景与限制。

直接用 python-docx 无法生成 PDF——它只能读写 .docx,不带排版渲染能力。真正可行的路径是调用系统级 Word 应用(Windows 上的 COM 接口)或借助 LibreOffice / headless Chrome 等外部工具。Windows 用户最稳、最接近原格式的方式是走 win32com.client;跨平台则推荐 libreoffice --headless 命令行。
Windows 下用 win32com 调用 Word 转换(保真度最高)
本质是让 Python 自动打开 Word、逐个打开 .docx、另存为 PDF。需本机安装 Microsoft Word(2016+),且不能后台被弹窗阻塞(比如“启用编辑”提示)。
- 安装依赖:
pip install pywin32,安装后建议运行python Scripts/pywin32_postinstall.py -install(尤其在虚拟环境中) - 关键限制:Word 进程必须无交互式弹窗,否则脚本会卡死。可在转换前加
word.Visible = False和word.DisplayAlerts = 0 - 保存时务必用完整绝对路径,相对路径易出错;目标 PDF 文件夹需提前存在
- 示例核心逻辑:
import win32com.client word = win32com.client.Dispatch("Word.Application") word.Visible = False word.DisplayAlerts = 0 for doc_path in docx_list: doc = word.Documents.Open(doc_path) pdf_path = doc_path.replace(".docx", ".pdf") doc.SaveAs(pdf_path, FileFormat=17) # 17 = wdFormatPDF doc.Close() word.Quit()
跨平台用 LibreOffice 命令行(Linux/macOS/Windows 均可)
LibreOffice 自带无头转换能力,不依赖 GUI,适合服务器或 CI 场景。但需提前安装 LibreOffice,并确保 soffice 命令在 PATH 中。
- 命令模板:
soffice --headless --convert-to pdf --outdir /output/dir /input/file.docx - 批量转换可用 shell 循环(Linux/macOS)或批处理(Windows),Python 中用
subprocess.run调用更可控 - 注意:LibreOffice 对复杂样式(尤其是嵌入字体、OLE 对象、某些页眉页脚)支持弱于原生 Word,转出 PDF 可能有微小偏移
- 避免并发过多导致 LibreOffice 崩溃,建议加
--nologo --nofirststartwizard参数,并控制进程数 ≤ 2
为什么不用 python-docx + reportlab 或 weasyprint?
因为 python-docx 仅解析结构,丢失全部渲染信息(字体嵌入、段落精确位置、分栏、文本框、页码等);reportlab 是绘图引擎,需手动重建布局,几百个文档根本不可维护;weasyprint 只吃 HTML/CSS,中间转 HTML 会进一步失真。这类组合只适合内容极简、只要文字的场景,不是“把 Word 转 PDF”的合理解。
常见报错和绕过方式
pywin32 报 Exception occurred. (0x80020009):通常是 Word 弹窗阻塞,检查是否开了“保护视图”或“启用内容”提示;临时关闭宏安全设置或改用管理员权限运行脚本。
-
soffice: command not found:macOS 上 LibreOffice 默认不加PATH,用/Applications/LibreOffice.app/Contents/MacOS/soffice全路径调用 - 中文乱码 PDF:LibreOffice 需预装对应中文字体(如 Noto Sans CJK),或在导出时加
--convert-to "pdf:writer_pdf_Export:{\"SelectPdfVersion\":{\"type\":\"long\",\"value\":\"17\"}}"指定编码 - Word 文档含密码:
Documents.Open()必须传Password参数,否则直接抛异常
真正麻烦的从来不是“怎么转”,而是 Word 文档本身是否干净——比如用了本地字体、内嵌了损坏的图片、含有受保护的节。批量处理前,先抽 3–5 个典型文档手动走一遍流程,比写完脚本再 debug 强十倍。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











