python-docx 是 Python 生态里专门用来创建和修改 Microsoft Word (.docx) 文件的库。它不依赖 Microsoft Office,纯 Python 实现,能像搭积木一样自由操控段落、文字样式、图片、页眉页脚、分节符等元素。下面用大量代码和一张核心流程图,带你彻底玩转这个库。
一、核心流程图
这张图概括了用 python-docx 工作的主线:无论操作什么对象,最终都是通过 Document 入口,构建各种块级元素和内联元素,最后保存。
二、安装与快速起步
一个最小化的 Hello World:
from docx import Documentdoc = Document()doc.add_paragraph('Hello, python-docx!')doc.save('hello.docx')
运行后就会在当前目录生成一个包含一句话的 Word 文档。
三、深入段落与 Run
python-docx 的核心概念是 段落 (Paragraph) 和 文本运行 (Run)。一个段落可以包含多个 Run,每个 Run 可以有不同的格式。
from docx import Documentfrom docx.shared import Pt, RGBColorfrom docx.enum.text import WD_ALIGN_PARAGRAPHdoc = Document()# 添加一个居中的标题段落title = doc.add_paragraph()title.alignment = WD_ALIGN_PARAGRAPH.CENTER# 在同一个段落中添加多个不同格式的 Runrun_title = title.add_run('自动化报告')run_title.bold = Truerun_title.font.size = Pt(22)run_title.font.color.rgb = RGBColor(0x42, 0x5E, 0xD2)# 换行后添加副标题run_sub = title.add_run('\n基于 Python-docx 生成')run_sub.font.size = Pt(12)run_sub.font.color.rgb = RGBColor(0x88, 0x88, 0x88)# 正文段落:一段普通文字p = doc.add_paragraph()p.add_run('这是第一句话,正常展示。')# 加一个加粗的 Runp.add_run(' 这句话会加粗。').bold = True# 加一个红色倾斜的 Runred_run = p.add_run(' 红色倾斜字体。')red_run.font.color.rgb = RGBColor(0xFF, 0x00, 0x00)red_run.italic = Truedoc.save('paragraph_demo.docx')
这里演示了在同一段落中混合多种格式,以及段落对齐方式。
四、样式全掌控:字体、间距、缩进
除了直接修改 Run 格式,还可以用“样式”成批管理。python-docx 内置了 Normal、Heading 1 等样式,也可以自定义。
from docx import Documentfrom docx.shared import Pt, Cmfrom docx.enum.style import WD_STYLE_TYPEdoc = Document()# 使用内置的 Heading 1 样式doc.add_heading('第一章:项目背景', level=1)# 自定义段落样式style = doc.styles.add_style('MyBodyStyle', WD_STYLE_TYPE.PARAGRAPH)style.font.name = '微软雅黑'style.font.size = Pt(11)style.paragraph_format.space_after = Pt(6)style.paragraph_format.first_line_indent = Cm(0.75) # 首行缩进p = doc.add_paragraph('这是一段应用了自定义样式的正文。' * 3, style='MyBodyStyle')# 直接修改某个段落的格式而不依赖样式p2 = doc.add_paragraph('直接操控段落格式的例子。')p2.paragraph_format.line_spacing = 1.5p2.paragraph_format.space_before = Pt(20)p2.paragraph_format.space_after = Pt(10)doc.save('style_demo.docx')
五、插入图片与设置大小
from docx import Documentfrom docx.shared import Inches, Cmdoc = Document()doc.add_paragraph('下方是一张嵌入的图片:')# 按英寸设置大小doc.add_picture('chart.png', width=Inches(4), height=Inches(3))# 按厘米设置大小doc.add_picture('logo.png', width=Cm(5))doc.save('picture_demo.docx')
图片会以原始宽高比嵌入,如果只指定宽度或高度,另一维度会自动按比例缩放。
六、页眉、页脚与页码
页眉页脚属于节 (Section) 的属性,可以分节设置不同的页眉页脚。
from docx import Documentfrom docx.shared import Ptdoc = Document()# 默认第一节section = doc.sections[0]header = section.headerheader.is_linked_to_previous = False # 断开与前一节的链接,允许独立设置header_para = header.paragraphs[0]header_para.text = '机密文件 - 仅限内部使用'header_para.style.font.size = Pt(9)# 页脚添加自动页码footer = section.footerfooter_para = footer.paragraphs[0]footer_para.text = '第 '# 插入 PAGE 域代码表示当前页码footer_para.add_run().add_field_code('PAGE')footer_para.add_run(' 页,共 ')footer_para.add_run().add_field_code('NUMPAGES')footer_para.add_run(' 页')doc.add_paragraph('正文内容...')doc.save('header_footer_demo.docx')
过 Word 域代码 PAGE 和 NUMPAGES,我们实现了动态页码,无需手动计算。
七、分节与页面设置
不同的节可以有不同的页面方向、纸张大小和页边距。
from docx import Documentfrom docx.shared import Cmfrom docx.enum.section import WD_ORIENTdoc = Document()# 第一节纵向sec1 = doc.sections[0]sec1.orientation = WD_ORIENT.PORTRAITsec1.page_width = Cm(21)sec1.page_height = Cm(29.7)sec1.top_margin = Cm(2.5)doc.add_paragraph('第一节:纵向页面内容。')# 添加新节,改为横向doc.add_section()sec2 = doc.sections[1]sec2.orientation = WD_ORIENT.LANDSCAPEnew_width, new_height = sec2.page_height, sec2.page_widthsec2.page_width = new_widthsec2.page_height = new_heightdoc.add_paragraph('第二节:横向页面内容,适合放宽表格或大图。')doc.save('section_demo.docx')
这种方式特别适合在报告中插入横向的大图表页面。
八、从模板文件构建内容
很多时候文档结构是固定的,只需要替换占位符。python-docx 没有内置的占位符替换函数,但我们可以遍历段落和 Run,并进行文本替换。
from docx import Documentdef replace_text_in_doc(doc, placeholder, replacement): for paragraph in doc.paragraphs: for run in paragraph.runs: if placeholder in run.text: run.text = run.text.replace(placeholder, replacement)doc = Document('template.docx') # 模板中写有 {{name}}、{{date}} 等replace_text_in_doc(doc, '{{name}}', '张三')replace_text_in_doc(doc, '{{date}}', '2026-05-06')doc.save('output.docx')
对于页眉、页脚甚至文本框中的文字,需要额外遍历 sections 和对应对象,思路类似。
九、生成完整报告的一个真实示例
下面整合以上技术,生成一份包含封面、目录占位、正文、图片和页眉页脚的报告。
from docx import Documentfrom docx.shared import Pt, Cm, Inches, RGBColorfrom docx.enum.text import WD_ALIGN_PARAGRAPHdoc = Document()# --- 封面 ---for _ in range(6): doc.add_paragraph() # 空行title = doc.add_paragraph()title.alignment = WD_ALIGN_PARAGRAPH.CENTERrun = title.add_run('2026 年春季数据分析报告')run.font.size = Pt(28)run.font.color.rgb = RGBColor(0x1A, 0x56, 0xDB)run.bold = Truesubtitle = doc.add_paragraph()subtitle.alignment = WD_ALIGN_PARAGRAPH.CENTERrun_sub = subtitle.add_run('技术部 · 生成时间: 2026-05-06')run_sub.font.size = Pt(14)run_sub.font.color.rgb = RGBColor(0x66, 0x66, 0x66)doc.add_page_break()# --- 正文章节 ---doc.add_heading('1. 引言', level=1)p = doc.add_paragraph()p.add_run('本报告基于一季度业务数据,采用 Python-docx 自动生成。')p.paragraph_format.first_line_indent = Cm(0.75)doc.add_heading('2. 数据概览', level=1)doc.add_paragraph('图 2-1 展示了最近三个月的关键指标变化。')# 插入图表图片doc.add_picture('monthly_trend.png', width=Inches(5.5))# --- 页眉页脚 ---section = doc.sections[0]header = section.headerheader.paragraphs[0].text = '内部报告 · 机密'footer = section.footerf_para = footer.paragraphs[0]f_para.text = '第 'f_para.add_run().add_field_code('PAGE')f_para.add_run(' 页 / 共 ')f_para.add_run().add_field_code('NUMPAGES')f_para.add_run(' 页')doc.save('auto_report.docx')
十、常用技巧与避坑指南
复制样式:同一个 Run 的字体属性可以复制给另一个 Run,利用 run.font 对象的属性直接赋值。
清除现有格式:新建的 Document 可能自带一个空段落,可以先用 doc.paragraphs[0].clear() 清空。
中文支持:确保字体名称是正确的系统字体,如 '微软雅黑' 或 '宋体';如果部署在 Linux,需安装对应字体。
运行顺序:add_run() 会紧接着上一个 Run 后面追加,不会自动换行,换行需要显式在文本中加入 \n 或用 add_paragraph()。
内存与性能:生成大型文档时,建议分批构建并适时保存,避免内存爆增。
python-docx 的强大在于它把 Word 文档结构抽象得非常清晰:Document → Section → Paragraph → Run。只要顺着这个层级去构造和修改,你就能创造出任何想要的专业文档,完全告别手工复制粘贴。现在就把你的报表、通知书、合同交给代码去完成吧!
编辑:余文彬
审校:余雨馨