因为 paragraph.text 是只读副本,需操作 run 或清空段落后重写;须递归处理表格、页眉页脚、文本框;替换用 re.escape 防误匹配;签章位用特定样式段落标记;pdf 乱码源于外部工具字体配置,非 python-docx 问题。

用 python-docx 替换占位符时,为什么 paragraph.text 改了但文档没变?
因为 python-docx 的 text 属性是只读副本,直接赋值不会写回文档对象。必须操作 run 级别内容,或清空段落再重写。
- 正确做法:遍历段落所有
run,用run.clear()+run.add_text();或用paragraph.clear()后调用paragraph.add_run() - 常见错误:写成
paragraph.text = "新内容"—— 这只会改 Python 对象里的字符串,不触发 docx 结构更新 - 注意:如果段落含表格、图片或分节符,
clear()会一并删除,需提前判断结构类型
合同里有表格和多级标题,怎么安全地批量替换 {{client_name}} 这类变量?
单纯遍历 document.paragraphs 不够,表格单元格、页眉页脚、文本框里的占位符都会被漏掉。必须递归扫描所有可编辑文本容器。
- 表格处理:遍历
table.cell(i, j).paragraphs,对每个paragraph做 run 级替换 - 页眉页脚:访问
section.header.paragraphs和section.footer.paragraphs(注意不同 section 可能独立) - 推荐封装函数:传入一个
element(可以是Document、Table、Header),统一处理其所有paragraphs属性 - 避免正则误匹配:占位符建议用
{{key}}格式,替换时用re.escape()包裹 key,防止.、*等字符触发意外匹配
生成的合同要带电子签章位置标记,怎么插入不可编辑的水印式标签?
Word 没有原生“签名域”,但可用 Field 或带样式的文本框模拟。最稳妥的是插入带特定样式名的空白段落,后期人工或第三方 SDK 定位填充。
- 插入方式:用
document.add_paragraph("【SIGNATURE_AREA:client_signature】"),再设paragraph.style = "SignaturePlaceholder" - 关键点:提前在模板中定义好名为
SignaturePlaceholder的样式,并设置字体小、颜色浅、无边框,避免干扰阅读 - 不要用图片水印——导出 PDF 时位置易偏移,且无法被签章工具识别
- 如需强约束,可在模板末尾加隐藏段落:
document.add_paragraph("SIG_POS_X:120,SIG_POS_Y:350").style = "Hidden",后续用坐标定位
导出为 PDF 时中文乱码或格式错乱,是字体问题还是渲染逻辑不对?
90% 是因为 python-docx 不控制 PDF 渲染,它只生成 .docx;转 PDF 必须依赖外部工具(如 Word COM、LibreOffice、docx2pdf),而字体嵌入策略由这些工具决定。
- docx 本身要指定中文字体:创建时用
style.font.name = "微软雅黑",同时设style.font._element.rPr.rFonts.set(qn("w:eastAsia"), "微软雅黑") - 转 PDF 推荐
docx2pdf(调用系统 Word):Windows 上稳定,macOS 需装 Microsoft Word;Linux 下要用 LibreOffice headless,且需预装对应中文字体 - 测试要点:生成的 .docx 文件用 Word 手动打开 → 是否显示正常?若手动转 PDF 也乱码,说明模板字体未生效,不是自动化环节的问题
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











