Microsoft PowerPoint — Python
Companion skill to ms-office-python (parent). For other areas see: ms-office-excel-python, ms-office-word-python, ms-office-graph-python, ms-office-enterprise-sso-python, ms-office-security-python.
Overview
.pptx (Office Open XML, OOXML) is a zip of XML parts that PowerPoint understands. python-pptx is the dominant Python library for reading and writing .pptx; it manipulates the XML model directly without needing PowerPoint installed. The 2026 ecosystem state is stable but in maintenance mode — see the Gotchas section.
python-pptx does NOT render slides — it manipulates the OOXML model only. Previews, thumbnails, and PDF exports route through PowerPoint itself or LibreOffice headless (soffice --headless --convert-to pdf). Plan the pipeline accordingly.
For generating PowerPoint decks from richer content sources (Markdown, data, templates), the production-grade path lives in the presentation-builder skill family. This skill covers Python-direct work on the .pptx format itself.
Library Selection
| Library | Purpose | Status (2026-05) | OS support | When to use | When NOT to use |
|---|---|---|---|---|---|
python-pptx |
Read + write .pptx |
Maintenance mode (stable, minor releases, no major roadmap) | All | All Python-direct .pptx work in 2026 |
Rendering / previewing — python-pptx manipulates the XML model only; it produces no images / PDFs / thumbnails. For previews, route through LibreOffice headless or PowerPoint COM (Windows-only). |
pypandoc |
Markdown / RST → .pptx via pandoc |
Active | All (requires pandoc binary) | Generating decks from Markdown source | Cell-level layout / animation control |
LibreOffice (soffice --headless) |
.pptx → PDF / PNG previews / video |
Active | All | Cross-platform conversion / preview generation | When you don't have LibreOffice (external binary dependency) |
pywin32 (win32com.client.Dispatch("PowerPoint.Application")) |
Drive PowerPoint via COM | Active | Windows only | Full-fidelity PowerPoint automation on Windows | Linux, headless containers, CI runners; flagged as legacy approach for new code |
presentation-builder skill family (existing) |
High-level deck-from-content workflows | Active (skill family) | N/A (Skill orchestration) | When building decks from structured data / outline / styling rules | Cell-level XML edits to a .pptx (use python-pptx) |
defusedxml |
XXE defence | Active | All | Any path that parses OOXML XML you don't fully control | (always include in security-conscious code) |
Install Commands
RHEL 9 / AlmaLinux 9 / Rocky 9
sudo dnf install -y python3.12 python3-pip python3-devel gcc-c++ libxml2-devel libxslt-devel
python3 -m pip install --upgrade pip
python3 -m pip install python-pptx defusedxml
# Optional, for PDF / preview / Markdown:
sudo dnf install -y libreoffice-core libreoffice-impress
python3 -m pip install pypandoc
Debian 12 / Ubuntu 24.04
sudo apt update
sudo apt install -y python3.12 python3-pip python3-dev build-essential libxml2-dev libxslt1-dev
python3 -m pip install --upgrade pip
python3 -m pip install python-pptx defusedxml
sudo apt install -y libreoffice-core libreoffice-impress
python3 -m pip install pypandoc
Windows 11
winget install --id Python.Python.3.12 -e --silent
python -m pip install --upgrade pip
python -m pip install python-pptx defusedxml pypandoc
# Optional, requires PowerPoint installed:
# python -m pip install pywin32
# Optional, headless conversion (no PowerPoint required):
# winget install --id LibreOffice.LibreOffice -e --silent
Capability Matrix
| Feature | python-pptx | LibreOffice headless | pypandoc | pywin32 COM |
|---|---|---|---|---|
Read .pptx |
yes | yes | yes | yes (PowerPoint required) |
Write .pptx |
yes | yes (via conversion) | yes | yes (PowerPoint required) |
| Convert to PDF | no | yes | yes (requires latex / chrome) | yes (PowerPoint required) |
| Convert to PNG / thumbnails | no | yes | partial | yes (PowerPoint required) |
| Embed images | yes | yes | yes | yes |
| Embed charts | partial (basic) | partial | partial | yes (full PowerPoint chart engine) |
| Animations / transitions | no | partial (limited) | no | yes (PowerPoint required) |
| Speaker notes | yes | yes | yes | yes |
| Slide layouts (template reuse) | yes | yes | partial | yes |
| Cross-platform | yes | yes | yes | NO (Windows + PowerPoint) |
Decision Sections
When to use python-pptx vs presentation-builder
| Question | Skill |
|---|---|
| "I have a deck template and need to fill in placeholders from data" | python-pptx (direct) |
| "I need an architecture-review deck with narrative + datavis + diagrams" | presentation-builder family |
| "I want to programmatically tweak slide N of an existing deck" | python-pptx (direct) |
| "I want to render Markdown to a deck with consistent styling" | pypandoc OR presentation-builder |
| "Preview / thumbnail / PDF of an existing deck" | LibreOffice headless OR (Windows only) PowerPoint COM |
The two paths are complementary, not exclusive. presentation-builder orchestrates higher-level pieces; python-pptx is the low-level primitive.
Preview / PDF / thumbnail generation
python-pptx produces no images. Three options for getting visual output from a .pptx:
- LibreOffice headless — cross-platform, no PowerPoint license required:
soffice --headless --convert-to pdf deck.pptx --outdir /tmp/out soffice --headless --convert-to png deck.pptx --outdir /tmp/out # first slide only - PowerPoint COM (Windows only, requires PowerPoint installed):
import win32com.client pp = win32com.client.Dispatch("PowerPoint.Application") pp.Visible = 1 # COM contract — required even for "headless" use deck = pp.Presentations.Open("deck.pptx", WithWindow=False) deck.SaveAs("deck.pdf", FileFormat=32) # PDF deck.Close(); pp.Quit() - External render service — Graph endpoint
/sites/.../drives/.../items/{id}/previewfor SharePoint-hosted decks, or commercial APIs (out of scope).
LibreOffice headless contention is the same issue as with Word — use a per-process UserInstallation profile in parallel CI runs.
Slide-layout reuse vs raw shapes
python-pptx supports two distinct workflows:
- Layout-driven (preferred): open a template
.pptx, iterateprs.slide_layouts, instantiate slides from layouts, fill in placeholders. Output looks consistent and lives in the same theme. - Shape-driven (last resort): add raw text frames, rectangles, images at absolute (left, top, width, height) coordinates. Works but produces decks that feel hand-mashed; templates / themes / dark mode handling break.
Always start layout-driven. Fall back to shape-driven only when the template doesn't expose the needed placeholder.
Canonical Pattern (modified C3)
Open a template, create slides from data, save — most common PowerPoint task.
# CONFIDENCE: minimal viable pattern — production hardening notes in the Security Hardening section below; full references/ guide planned (v1.1).
from pptx import Presentation
from pptx.util import Inches
prs = Presentation("template.pptx")
title_layout = prs.slide_layouts[0] # Title slide layout (verify index against your template)
for record in [{"title": "Q1", "subtitle": "Revenue up 12%"}, {"title": "Q2", "subtitle": "Revenue up 18%"}]:
slide = prs.slides.add_slide(title_layout)
slide.placeholders[0].text = record["title"] # title placeholder
slide.placeholders[1].text = record["subtitle"] # subtitle placeholder
prs.save("output.pptx")
The pattern enforces three things: template-driven layouts (consistent visual), data-driven slide generation (not hand-coded shapes), no rendering side-effects (output is .pptx only — preview is a separate step).
Security Hardening
See ms-office-security-python for the consolidated checklist. Area-specific items:
- Pair
python-pptxwithdefusedxml.python-pptxuseslxmlinternally; the OOXML parsing path is XXE-exposed in olderlxmlversions. - For untrusted
.pptxinput, parse in a sandboxed subprocess or container. Embedded OLE objects, linked media, and external relationships can pull in arbitrary network content if the deck is later opened in PowerPoint. - Inspect
prs.core_properties(author, last_modified_by, comments, keywords) before publishing externally — PII / internal usernames live here. - Slides can carry slide notes that are not displayed but ship with the file. When generating decks from internal data, ensure speaker-notes content is intentional — don't leak comments / TODOs.
- Embedded media files (videos, audio) increase deck size and can carry their own malicious payloads. Strip or replace
slide.shapesof typeMediabefore publishing externally if provenance is unclear. - When converting
.pptxto PDF via LibreOffice headless, run with--norestore --nodefault --headless --env:UserInstallation=file:///tmp/lo-user-$$in parallel CI to avoid lockfile contention. - Refuse to process decks larger than a hard
MAX_BYTEScap (e.g. 200 MB). Real decks usually fit; pathological ones don't. - Embedded fonts (in some templates) carry copyright metadata. Ensure license compatibility before redistributing.
Selection Cheatsheet
- "Read a .pptx programmatically" →
python-pptx - "Generate a deck from data + template" →
python-pptxwith layout-driven flow - "Generate a deck from Markdown" →
pypandocOR thepresentation-builderskill family - "Convert .pptx → PDF on Linux" → LibreOffice headless
- "Convert .pptx → PDF on Windows with PowerPoint" →
pywin32COM (legacy; LibreOffice also works) - "Generate slide-N thumbnails" → LibreOffice headless or external service (no Python-direct option)
- "Read speaker notes" →
slide.notes_slide.notes_text_frame.text
Gotchas
python-pptxis in maintenance mode as of 2026-05 — stable, minor releases, no major roadmap. It will continue to work for current OOXML, but if Office formats evolve significantly the response may lag. Pin a known-good version, runpip-auditregularly (delegate todep-currency-check), and watch the GitHub repo.python-pptxdoes NOT render — no thumbnails, no PDF, no images. This bites every newcomer; plan the rendering step explicitly.- Slide-layout indices are template-specific. Hardcoding
prs.slide_layouts[0]works for the default template but breaks the moment someone substitutes a customised template. Look up bylayout.namefor portable code. - Embedded charts in
python-pptxare basic (bar, line, pie). Sankeys, treemaps, complex composites must be pre-rendered as images and inserted asPictureshapes. - Speaker notes silently inherit theme fonts; setting
notes.text_frame.text = ...strips font / colour. Usenotes.text_frame.paragraphs[0].add_run(...)for styled notes. prs.save(path)overwrites without warning. Layer file-existence checks if overwrite is undesirable.python-pptxcannot edit.ppt(legacy Office 97-2003 PowerPoint format). Convert through LibreOffice first.
Platform routing — rendering is the only OS-dependent step
python-pptx itself is pure Python and behaves identically on Windows, macOS and Linux. The
split appears the moment you need a PDF or a thumbnail, because python-pptx renders nothing:
| Rendering route | Windows | macOS | Linux / CI |
|---|---|---|---|
LibreOffice headless (soffice --headless --convert-to pdf) |
✅ | ✅ | ✅ |
PowerPoint via COM (pywin32) |
✅ | ❌ no COM on macOS | ❌ |
PowerPoint via Apple Events (xlwings-style / AppleScript) |
❌ | ⚠️ needs Office and a TCC grant and a logged-in user | ❌ |
LibreOffice headless is the only row that is green everywhere, which makes it the default for
any pipeline that has to run on more than one machine. There is no COM on macOS — the Mac path
is Apple Events, and it cannot be granted headlessly, so it is unavailable on CI exactly as COM is
on Linux. See ms-office-python/references/macos-automation.md.
Update Triggers (per Codex M-1 — alf will scan these)
- Major version bump of:
python-pptx,lxml,pypandoc. - New OOXML /
.pptxschema change announced by Microsoft (rare but happens). - CVE published against
lxml(XXE class). - LibreOffice CLI flag changes for the
--convert-tofamily. python-pptxmoving back to active development (would unlock chart / animation coverage).- Annual review on: 2027-05-22.
See Also
| Need | Skill |
|---|---|
| Excel manipulation | ms-office-excel-python |
| Word document generation | ms-office-word-python |
| Generating a structured presentation (narrative + datavis + diagrams) | presentation-builder family (presentation-narrative, presentation-datavis, presentation-diagrams, presentation-styling, presentation-renderer) |
| Sending a deck through Outlook / posting to Teams via Graph | ms-office-graph-python |
| Hardening / validator / checklist | ms-office-security-python |