Django-Admin.ru

python-pptx: создание презентаций PowerPoint из Python

Библиотека python-pptx: установка через pip install python-pptx, слайды с текстом, картинками, таблицами и диаграммами, чтение готовой презентации.

Редакция Django-Admin.ru
· обновлено · 9 мин чтения

Содержание · 11 разделов
  1. Установка python-pptx
  2. Частые ошибки при установке
  3. Презентация, макеты и плейсхолдеры
  4. Размеры: Inches, Pt, Cm
  5. Текст и форматирование
  6. Картинки
  7. Таблицы
  8. Диаграммы
  9. Чтение и правка готовой презентации
  10. Частые ошибки
  11. AttributeError: ‘NoneType’ object has no attribute ‘text’
  12. PackageNotFoundError: Package not found at ’…’
  13. Слайд создан, но текст не виден
  14. PermissionError при сохранении
  15. Форматирование пропало после замены текста
  16. Частые вопросы
  17. Можно ли сохранить презентацию в PDF или картинки?
  18. Как отцентрировать картинку на слайде?
  19. Как удалить пустой плейсхолдер?
  20. Как скопировать слайд?
  21. Как отдать презентацию из веб-приложения без сохранения на диск?
  22. Что делать с ошибкой AttributeError: module ‘collections’ has no attribute …?
  23. Итог

python-pptx — библиотека для создания и редактирования презентаций PowerPoint (.pptx) из кода на Python. С её помощью отчёты со слайдами, таблицами и диаграммами собираются автоматически, без ручной работы в PowerPoint. Быстрый ответ — установка и первый слайд:

pip install python-pptx
from pptx import Presentation

prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[0])  # титульный макет
slide.shapes.title.text = "Отчёт за квартал"
slide.placeholders[1].text = "Подготовлено автоматически на Python"
prs.save("report.pptx")

Обратите внимание: пакет называется python-pptx, а модуль для импорта — pptx. Ниже — установка и типичные ошибки с именем пакета, макеты слайдов, текст и форматирование, картинки, таблицы, диаграммы, чтение готовых файлов. Примеры проверены на python-pptx 1.0.2 и Python 3.12.

Установка python-pptx

Устанавливайте пакет в виртуальное окружение проекта:

# Windows
py -m pip install python-pptx

# macOS / Linux
python3 -m pip install python-pptx

Вместе с ним установятся зависимости: lxml (работа с XML внутри .pptx), Pillow (картинки), XlsxWriter (данные для диаграмм) и typing-extensions. Сам PowerPoint для работы библиотеки не нужен — она пишет файл напрямую, поэтому работает и на Linux-сервере.

Проверка:

import pptx

print(pptx.__version__)  # → 1.0.2

Частые ошибки при установке

Запросы «pip install python pptx» и «python pptx install» обычно появляются после одной из этих ошибок:

  • Пробел вместо дефиса. Команда pip install python pptx пытается поставить два пакета — python и pptx — и завершается ошибкой:

    ERROR: Could not find a version that satisfies the requirement python (from versions: none)
    ERROR: No matching distribution found for python
  • Имя модуля вместо имени пакета. pip install pptx тоже не сработает: No matching distribution found for pptx. Правильно — pip install python-pptx.

  • Неправильный импорт. import python_pptx даёт ModuleNotFoundError: No module named 'python_pptx'. Импортируйте pptx: from pptx import Presentation.

  • Пакет стоит в другом интерпретаторе. Если ModuleNotFoundError: No module named 'pptx' появляется после успешной установки, pip и скрипт используют разные Python. Запускайте pip как python -m pip из того же окружения — подробнее в статье про ModuleNotFoundError и в руководстве по установке библиотек.

Презентация, макеты и плейсхолдеры

Presentation() без аргументов создаёт пустую презентацию на встроенном шаблоне. Presentation("template.pptx") открывает существующий файл — так можно взять корпоративный шаблон с фирменными цветами и шрифтами.

Слайд добавляется по макету (layout). Во встроенном шаблоне их 11:

ИндексМакетЧто на слайде
0Title Slideзаголовок и подзаголовок
1Title and Contentзаголовок и блок со списком
2Section Headerзаголовок раздела
3Two Contentзаголовок и две колонки
5Title Onlyтолько заголовок
6Blankпустой слайд

Список макетов любого шаблона можно вывести так:

for i, layout in enumerate(prs.slide_layouts):
    print(i, layout.name)

Плейсхолдеры — заготовленные поля макета. Заголовок доступен как slide.shapes.title, остальные поля — через slide.placeholders[idx]. Пример слайда со списком:

slide = prs.slides.add_slide(prs.slide_layouts[1])
slide.shapes.title.text = "Итоги"

body = slide.placeholders[1].text_frame
body.text = "Выручка выросла на 12%"       # первый пункт
p = body.add_paragraph()
p.text = "Новых клиентов: 340"
p = body.add_paragraph()
p.text = "Из них корпоративных: 25"
p.level = 1                                # вложенный пункт

Встроенный шаблон имеет формат 4:3 (10 × 7,5 дюйма). Для широкоформатных слайдов 16:9 задайте размер сразу после создания презентации:

from pptx.util import Inches

prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)

Размеры: Inches, Pt, Cm

Координаты и размеры в .pptx хранятся в единицах EMU (914 400 на дюйм). Вручную их считать не нужно — используйте помощники из pptx.util:

from pptx.util import Inches, Pt, Cm

print(Inches(1), Cm(2), Pt(32))  # → 914400 720000 406400

Позиция фигуры задаётся отступом слева (left) и сверху (top) от левого верхнего угла слайда, затем шириной и высотой.

Текст и форматирование

На пустой слайд текст добавляют текстовым полем. Текст в python-pptx устроен в три уровня: text_frame → абзацы (paragraphs) → фрагменты (runs). Шрифт задаётся у фрагмента, выравнивание — у абзаца:

from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN

slide = prs.slides.add_slide(prs.slide_layouts[6])  # пустой макет
box = slide.shapes.add_textbox(Inches(1), Inches(1), Inches(8), Inches(1))
tf = box.text_frame
tf.word_wrap = True

p = tf.paragraphs[0]
p.alignment = PP_ALIGN.CENTER
run = p.add_run()
run.text = "Крупный красный текст"
run.font.size = Pt(32)
run.font.bold = True
run.font.name = "Arial"
run.font.color.rgb = RGBColor(0xC0, 0x00, 0x00)

Фигуры — прямоугольники, стрелки, овалы — добавляет add_shape():

from pptx.enum.shapes import MSO_SHAPE

shape = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(1), Inches(3), Inches(3), Inches(1))
shape.text = "Фигура"
shape.fill.solid()
shape.fill.fore_color.rgb = RGBColor(0x1F, 0x77, 0xB4)

Картинки

add_picture() вставляет PNG, JPEG, GIF и другие растровые форматы. Если указать только ширину, высота подберётся с сохранением пропорций:

slide = prs.slides.add_slide(prs.slide_layouts[5])
slide.shapes.title.text = "График"
pic = slide.shapes.add_picture("chart.png", Inches(1), Inches(1.5), width=Inches(8))

Так в презентацию попадают графики, построенные в Matplotlib: сохраните фигуру через fig.savefig("chart.png", dpi=150) и вставьте файл на слайд.

Таблицы

add_table() создаёт таблицу нужного размера, ячейки заполняются через cell(строка, столбец):

slide = prs.slides.add_slide(prs.slide_layouts[5])
slide.shapes.title.text = "Продажи по городам"

data = [("Город", "Продажи"), ("Москва", "1200"), ("Казань", "800"), ("Пермь", "450")]
rows, cols = len(data), len(data[0])
table = slide.shapes.add_table(rows, cols, Inches(1), Inches(1.5), Inches(8), Inches(2)).table

for r, row in enumerate(data):
    for c, value in enumerate(row):
        table.cell(r, c).text = value      # только строки

table.columns[0].width = Inches(5)
table.columns[1].width = Inches(3)

В ячейку записывается только строка: число вызовет AttributeError: 'int' object has no attribute 'split', поэтому преобразуйте значения через str() или f-строки. Данные для таблицы удобно готовить в pandas — например, перебрать строки DataFrame через df.itertuples().

Диаграммы

В отличие от вставленной картинки, нативная диаграмма PowerPoint остаётся редактируемой: данные можно поменять прямо в PowerPoint.

from pptx.chart.data import CategoryChartData
from pptx.enum.chart import XL_CHART_TYPE, XL_LEGEND_POSITION

slide = prs.slides.add_slide(prs.slide_layouts[5])
slide.shapes.title.text = "Выручка"

chart_data = CategoryChartData()
chart_data.categories = ["Янв", "Фев", "Мар"]
chart_data.add_series("2026", (120, 95, 140))

chart = slide.shapes.add_chart(
    XL_CHART_TYPE.COLUMN_CLUSTERED, Inches(1), Inches(1.5), Inches(8), Inches(5), chart_data
).chart
chart.has_legend = True
chart.legend.position = XL_LEGEND_POSITION.BOTTOM
chart.legend.include_in_layout = False

Другие типы: XL_CHART_TYPE.LINE, XL_CHART_TYPE.PIE, XL_CHART_TYPE.BAR_CLUSTERED. Несколько рядов данных добавляются повторными вызовами add_series().

Заметки докладчика к слайду:

slide.notes_slide.notes_text_frame.text = "Сказать про сезонность"
prs.save("report.pptx")

Чтение и правка готовой презентации

Чтобы извлечь текст, переберите слайды и фигуры. У таблиц нет text_frame, их проверяют отдельно через has_table:

from pptx import Presentation

prs = Presentation("report.pptx")
for number, slide in enumerate(prs.slides, start=1):
    for shape in slide.shapes:
        if shape.has_text_frame and shape.text_frame.text:
            print(number, shape.text_frame.text)
        elif shape.has_table:
            for row in shape.table.rows:
                print(number, [cell.text for cell in row.cells])

Фрагмент вывода для презентации из примеров выше:

1 Отчёт за квартал
1 Подготовлено автоматически на Python
...
5 Продажи по городам
5 ['Город', 'Продажи']
5 ['Москва', '1200']

Для замены текста в шаблоне меняйте run.text, а не text_frame.text: присваивание text_frame.text удаляет фрагменты вместе с их форматированием.

replacements = {"Отчёт за квартал": "Отчёт за III квартал"}

for slide in prs.slides:
    for shape in slide.shapes:
        if not shape.has_text_frame:
            continue
        for paragraph in shape.text_frame.paragraphs:
            for run in paragraph.runs:
                for old, new in replacements.items():
                    if old in run.text:
                        run.text = run.text.replace(old, new)

prs.save("report_q3.pptx")

PowerPoint иногда разбивает одно слово на несколько фрагментов (например, после проверки орфографии), и тогда метка не найдётся в одном run. Для шаблонов набирайте метки вроде client_name одним действием, без последующей правки.

Частые ошибки

AttributeError: ‘NoneType’ object has no attribute ‘text’

У макета нет заголовка, а код обращается к slide.shapes.title — например, на пустом макете 6 (Blank). Выберите макет с заголовком или добавьте текстовое поле через add_textbox().

PackageNotFoundError: Package not found at ’…’

Библиотека не нашла файл по указанному пути или файл не является .pptx. Проверьте путь (относительный путь считается от текущей папки запуска) и формат: старые презентации .ppt и файлы других типов python-pptx не открывает — сначала сохраните презентацию в PowerPoint как .pptx.

Слайд создан, но текст не виден

Текстовое поле вышло за пределы слайда: координаты больше prs.slide_width или prs.slide_height. Для макета 4:3 ширина — 10 дюймов, для 16:9 — 13,333 дюйма.

PermissionError при сохранении

Файл с тем же именем открыт в PowerPoint, и Windows не даёт его перезаписать. Закройте презентацию или сохраните под другим именем.

Форматирование пропало после замены текста

Использовано shape.text = ... или text_frame.text = ... — они пересоздают абзацы. Меняйте текст на уровне run.text, как в примере выше.

Частые вопросы

Можно ли сохранить презентацию в PDF или картинки?

Средствами python-pptx — нет: библиотека не рисует слайды, а только записывает XML внутри .pptx. Для конвертации нужна программа, которая умеет отображать презентации. На сервере обычно используют LibreOffice в фоновом режиме:

soffice --headless --convert-to pdf report.pptx

На Windows с установленным PowerPoint можно также управлять им через COM-интерфейс (пакет pywin32).

Как отцентрировать картинку на слайде?

Вставьте картинку с нужной шириной, а затем вычислите отступы из размеров слайда и самой картинки:

pic = slide.shapes.add_picture("chart.png", 0, 0, width=Inches(6))
pic.left = (prs.slide_width - pic.width) // 2
pic.top = (prs.slide_height - pic.height) // 2

Для текста по центру используется выравнивание абзаца PP_ALIGN.CENTER из раздела про форматирование.

Как удалить пустой плейсхолдер?

Незаполненный плейсхолдер в режиме показа не виден, но в редакторе PowerPoint остаётся пустой рамкой с подсказкой. Публичного метода удаления нет, поэтому элемент убирают из XML слайда:

for ph in list(slide.placeholders):
    if ph.has_text_frame and not ph.text_frame.text:
        ph._element.getparent().remove(ph._element)

Атрибут _element — внутренний API библиотеки; проще выбрать макет без лишних полей, например Title Only или Blank.

Как скопировать слайд?

Готового метода копирования слайдов в python-pptx нет. Надёжнее не копировать слайды, а генерировать их заново из данных: подготовьте шаблон .pptx с нужными макетами и создавайте каждый слайд через add_slide() с нужным макетом. Копирование фигур через XML возможно, но картинки и диаграммы сломаются, если вручную не перенести их связи (relationships) с файлами внутри пакета.

Как отдать презентацию из веб-приложения без сохранения на диск?

prs.save() принимает не только путь, но и файловый объект. Сохраните презентацию в io.BytesIO и верните байты в ответе с типом application/vnd.openxmlformats-officedocument.presentationml.presentation:

import io

buf = io.BytesIO()
prs.save(buf)
data = buf.getvalue()  # байты готового .pptx

Что делать с ошибкой AttributeError: module ‘collections’ has no attribute …?

Установлена старая версия python-pptx (до 0.6.22), несовместимая с Python 3.10 и новее. Обновите пакет: pip install -U python-pptx.

Итог

Установите пакет командой pip install python-pptx, импортируйте модуль pptx и собирайте презентацию из слайдов по макетам: текст — через плейсхолдеры и add_textbox(), данные — через add_table() и add_chart(), графики — через add_picture(). Генерацию отчётов удобно встроить в сценарии автоматизации на Python. Другие полезные пакеты собраны в обзоре библиотек Python, полный справочник API — в документации python-pptx.

  • #Python
  • #python-pptx
  • #PowerPoint
  • #Автоматизация
↑ ↓ выборEnter открытьEsc закрыть