python-docx: Create and Edit Word Documents with Python (2026)
Office automation is not only Excel and PDF. After covering openpyxl for Excel and pypdf for PDFs, the natural third pillar is Word. With python-docx 1.2.0 on Python 3.13.5 you can create .docx files, style runs, build tables, and open existing documents for edits — all without launching Microsoft Word.
Install python-docx
pip install python-docx
Confirm the install:
python -c "import docx; print(docx.__version__)"
# 1.2.0
Create a Document with headings, styled runs, and a table
Start from Document(), add structure, then save(). The script below builds a weekly sales report and prints the real file size and paragraph count from a live run.
from docx import Document
from docx.shared import Pt, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from pathlib import Path
out = Path("weekly_report.docx")
doc = Document()
doc.add_heading("Weekly Sales Report", level=1)
doc.add_heading("Summary", level=2)
p = doc.add_paragraph()
run = p.add_run("Status: ")
run.bold = True
run = p.add_run("On track")
run.italic = True
run.font.color.rgb = RGBColor(0x00, 0x80, 0x00)
doc.add_paragraph(
"This report was generated automatically with python-docx. "
"Headings, styled runs, and a table are included below."
)
table = doc.add_table(rows=1, cols=3)
table.style = "Table Grid"
hdr = table.rows[0].cells
hdr[0].text = "Region"
hdr[1].text = "Units"
hdr[2].text = "Revenue"
for region, units, revenue in [
("North", "1,240", "$48,200"),
("South", "980", "$36,750"),
("East", "1,510", "$55,100"),
]:
row = table.add_row().cells
row[0].text = region
row[1].text = units
row[2].text = revenue
footer = doc.add_paragraph()
footer.alignment = WD_ALIGN_PARAGRAPH.CENTER
fr = footer.add_run("Generated with python-docx")
fr.font.size = Pt(9)
fr.font.color.rgb = RGBColor(0x66, 0x66, 0x66)
doc.save(out)
print(f"Saved: {out}")
print(f"File size: {out.stat().st_size} bytes")
print(f"Paragraphs: {len(doc.paragraphs)}")
print(f"Tables: {len(doc.tables)}")
Actual output (Python 3.13.5, python-docx 1.2.0):
Saved: weekly_report.docx
File size: 37024 bytes
Paragraphs: 6
Tables: 1
Key ideas:
add_heading(text, level=…)sets outline styles.- A paragraph is a container of runs; bold, italic, color, and font size apply per run.
add_tableplusTable Gridgives a bordered table you can fill cell by cell.
Open and edit an existing .docx
Pass a path to Document(...) to load a file, append sections, then save under a new name (or overwrite).
from docx import Document
from pathlib import Path
path = Path("weekly_report.docx")
doc = Document(path)
doc.add_heading("Notes", level=2)
doc.add_paragraph(
"East region led revenue this week. "
"Review South inventory levels next sprint."
)
edited = path.with_name("weekly_report_edited.docx")
doc.save(edited)
check = Document(edited)
print(f"Opened: {path.name}")
print(f"Saved edited: {edited.name}")
print(f"Edited file size: {edited.stat().st_size} bytes")
print(f"Paragraphs after edit: {len(check.paragraphs)}")
print(f"Tables: {len(check.tables)}")
print("Paragraph preview:")
for i, p in enumerate(check.paragraphs[:8]):
text = (p.text or "").strip()
if text:
print(f" [{i}] {p.style.name}: {text[:70]}")
Actual output:
Opened: weekly_report.docx
Saved edited: weekly_report_edited.docx
Edited file size: 37082 bytes
Paragraphs after edit: 8
Tables: 1
Paragraph preview:
[0] Heading 1: Weekly Sales Report
[1] Heading 2: Summary
[2] Normal: Status: On track
[3] Normal: This report was generated automatically with python-docx. Headings, st
[5] Normal: Generated with python-docx
[6] Heading 2: Notes
[7] Normal: East region led revenue this week. Review South inventory levels next
After the edit you have eight paragraphs and the original table intact — useful for report pipelines that inject a Notes block each week.
When to reach for python-docx
- Batch-generating invoices, proposals, or status reports from Python data.
- Filling templates: open a branded
.docx, replace placeholders in paragraphs, save copies. - Combining with tabular workflows — for example exporting summaries alongside PyArrow tables and Parquet datasets.
python-docx does not render Word UI or run VBA macros; it reads and writes the Open XML package. That is exactly what you want for headless servers and CI jobs.
Quick checklist
pip install python-docxDocument()→ headings → runs → table →save()Document(path)→ mutate →save()again- Assert file size / paragraph counts in tests so broken templates fail fast
With Excel (openpyxl), PDF (pypdf), and Word (python-docx) covered, your Python stack can drive the full office document loop from one venv.