PyMuPDF vs pypdf — какую библиотеку PDF для Python выбрать?
PyMuPDF и pypdf — две из самых популярных Python-библиотек для PDF, но обе имеют существенные компромиссы. PyMuPDF быстр, но ограничен лицензией AGPL-3.0. pypdf распространяется под разрешительной лицензией, но в 15 раз медленнее. Эта страница сравнивает их напрямую и показывает, почему PDF Oxide — лучший выбор, чем оба.
Коротко: PDF Oxide в 5.8 раз быстрее PyMuPDF, в 15 раз быстрее pypdf, распространяется под MIT-лицензией и имеет больше возможностей, чем обе библиотеки — включая встроенный вывод в Markdown/HTML, поддержку XFA-форм и OCR без системных зависимостей.
Краткое сравнение
| PyMuPDF | pypdf | PDF Oxide | |
|---|---|---|---|
| Лицензия | AGPL-3.0 | BSD-3 | MIT |
| Язык | C (MuPDF) | Чистый Python | Rust + PyO3 |
| Среднее время извлечения | 4.6 мс | 12.1 мс | 0.8 мс |
| Время извлечения p99 | 28 мс | 97 мс | 9 мс |
| Успешность (3,830 PDF) | 99.3% | 98.4% | 100% |
| Извлечение текста | Да | Да | Да |
| Позиции символов | Да | Частично | Да |
| Извлечение изображений | Да | Да | Да |
| Поля форм | Чтение + запись | Чтение + запись | Чтение + запись |
| Создание PDF | Да | Ограниченно (только объединение) | Да (Markdown/HTML) |
| Вывод в Markdown | Нет | Нет | Да |
| Вывод в HTML | Нет | Нет | Да |
| Рендеринг | Да | Нет | Да |
| OCR | Tesseract | Нет | Встроенный (PaddleOCR) |
| Размер при установке | ~20 МБ | ~1 МБ | ~5 МБ |
| Шифрование | Чтение + запись | Чтение + запись | Чтение + запись |
| Поиск | Да | Нет | Regex + пространственный |
| Версии Python | 3.8–3.12 | 3.6+ | 3.8–3.14 |
PyMuPDF быстрее и функциональнее pypdf, но его лицензия AGPL неприемлема для многих коммерческих проектов. pypdf легче и BSD-лицензирована, но значительно медленнее и ограниченнее в возможностях извлечения. PDF Oxide сочетает скоростное преимущество нативного движка со свободой разрешительной лицензии.
Лицензирование: AGPL vs BSD vs MIT
Различие в лицензировании между PyMuPDF и pypdf часто является решающим фактором при выборе.
PyMuPDF — AGPL-3.0
PyMuPDF оборачивает MuPDF, лицензированный под AGPL-3.0. Это строгая copyleft-лицензия. Если вы распространяете любое ПО, использующее PyMuPDF — включая SaaS-приложения, Docker-контейнеры, веб-сервисы, десктопные и CLI-приложения — всё ваше приложение должно быть выпущено под AGPL-3.0. Это означает публикацию полного исходного кода под той же лицензией.
Альтернатива — приобретение коммерческой лицензии у Artifex, компании-разработчика MuPDF. Artifex не публикует цены; нужно обращаться в отдел продаж. Коммерческие лицензии обычно ежегодные и привязаны к приложению.
AGPL затрагивает вас, если:
- Вы распространяете продукт, включающий PyMuPDF (десктоп, мобильное приложение, Electron)
- Вы запускаете SaaS или веб-сервис, обрабатывающий PDF с PyMuPDF
- Вы распространяете Docker-образы с PyMuPDF
- Вы предоставляете API, использующий PyMuPDF внутренне
AGPL не затрагивает вас, если:
- Ваш проект уже опубликован под AGPL-совместимой лицензией
- Вы используете PyMuPDF только для внутренних инструментов, которые не распространяются
pypdf — BSD-3
pypdf использует лицензию BSD 3-Clause, которая является разрешительной. Вы можете использовать pypdf в коммерческих продуктах, закрытом ПО и SaaS-приложениях без обязательств по открытию кода. Единственное требование — сохранение уведомления об авторских правах при распространении.
PDF Oxide — MIT
PDF Oxide распространяется под лицензией MIT — самой разрешительной из распространённых open-source лицензий. Используйте в любом контексте (коммерческий, проприетарный, SaaS, open source) без ограничений, кроме включения текста лицензии.
Обзор лицензирования
| Сценарий | PyMuPDF (AGPL) | pypdf (BSD) | PDF Oxide (MIT) |
|---|---|---|---|
| Коммерческий продукт | Требуется лицензия | Да | Да |
| Закрытый SaaS | Требуется лицензия | Да | Да |
| Распространение Docker | Требуется лицензия | Да | Да |
| Внутренние инструменты | Да | Да | Да |
| Open-source (AGPL-совместимый) | Да | Да | Да |
| Open-source (MIT/BSD/Apache) | Нет | Да | Да |
Для коммерческих проектов, где важно соответствие лицензиям, pypdf и PDF Oxide — безопасные варианты. PyMuPDF требует либо открытия исходного кода приложения, либо приобретения коммерческой лицензии.
Бенчмарки скорости
Все benchmark проведены на одном корпусе из 3 830 PDF — три независимых, публично доступных набора тестов (veraPDF, Mozilla pdf.js, DARPA SafeDocs), охватывающих все версии спецификации PDF (1.0–2.0), зашифрованные файлы, кодировки CJK, сложные макеты и повреждённые документы.
Скорость извлечения текста
| Библиотека | Среднее | p99 | Относительно PDF Oxide |
|---|---|---|---|
| PDF Oxide | 0.8 мс | 9 мс | 1x |
| PyMuPDF | 4.6 мс | 28 мс | в 5.8 раз медленнее |
| pypdf | 12.1 мс | 97 мс | в 15.1 раз медленнее |
PyMuPDF в 2.6 раза быстрее pypdf, потому что делегирует парсинг C-движку MuPDF. pypdf выполняет всё на чистом Python — парсинг, декодирование шрифтов, сборку текста — каждая операция несёт накладные расходы интерпретатора.
PDF Oxide быстрее обоих, потому что его ядро на Rust обрабатывает весь парсинг PDF, декодирование шрифтов и компоновку текста нативно через PyO3, и только финальный результат пересекает границу Python. Нет накладных расходов на подпроцессы, нет связывания с C-библиотекой через ctypes и нет узкого места интерпретатора.
Надёжность
| Библиотека | Валидных PDF пройдено | Успешность |
|---|---|---|
| PDF Oxide | 3,823 / 3,823 | 100% |
| PyMuPDF | 3,796 / 3,823 | 99.3% |
| pypdf | 3,762 / 3,823 | 98.4% |
PyMuPDF не справляется с 27 валидными PDF в корпусе. pypdf — с 61. В обоих случаях это валидные PDF-файлы, на которых библиотека либо падает, либо возвращает пустой/некорректный текст. PDF Oxide обрабатывает все 3 823 валидных PDF без ошибок.
7 непрошедших файлов в полном корпусе из 3 830 — это намеренно повреждённые тестовые фикстуры (отсутствующий заголовок PDF, повреждённые фаззингом каталоги, невалидные потоки xref), исключённые из расчёта успешности для всех библиотек.
Что это значит на практике
Для пайплайна, обрабатывающего тысячи PDF ежедневно, успешность PyMuPDF 99.3% означает примерно 7 ошибок на 1 000 документов. У pypdf 98.4% означает 16 ошибок на 1 000. Это документы, для которых нужна логика резервной обработки, ручная проверка или смирение с потерей данных.
100% успешность PDF Oxide на тестовом корпусе означает меньше граничных случаев в production.
Сравнение возможностей
Извлечение текста
Все три библиотеки поддерживают базовое извлечение текста. Стили API различаются:
PyMuPDF:
import fitz
doc = fitz.open("report.pdf")
page = doc[0]
text = page.get_text()
print(text)
pypdf:
from pypdf import PdfReader
reader = PdfReader("report.pdf")
text = reader.pages[0].extract_text()
print(text)
PDF Oxide:
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
text = doc.extract_text(0)
print(text)
PyMuPDF использует объектную модель страниц (doc[0] возвращает страницу). pypdf использует паттерн ридер/страницы. PDF Oxide работает с индексами страниц напрямую.
Для извлечения на уровне символов (позиции, размеры шрифтов, bounding box) PyMuPDF предоставляет get_text("dict"), возвращающий вложенную структуру словарей. pypdf предлагает частичные данные о позициях символов. PDF Oxide предоставляет extract_chars() с bounding box и метаданными шрифта для каждого символа.
Конвертация в Markdown
Это существенный дифференциатор. Многим LLM- и RAG-пайплайнам нужен Markdown-вывод из PDF.
PyMuPDF:
# PyMuPDF не имеет встроенной конвертации в Markdown.
# Нужен pymupdf4llm — отдельный пакет:
import pymupdf4llm
md = pymupdf4llm.to_markdown("paper.pdf")
pymupdf4llm работает, но в 69 раз медленнее встроенной конвертации PDF Oxide (55.5 мс в среднем против 0.8 мс). Это отдельная зависимость со своим циклом поддержки.
pypdf:
# pypdf не поддерживает конвертацию в Markdown.
# Потребуется внешняя цепочка инструментов (например, извлечь текст,
# затем использовать отдельную библиотеку для структурирования в Markdown).
PDF Oxide:
from pdf_oxide import PdfDocument
doc = PdfDocument("paper.pdf")
md = doc.to_markdown(0, detect_headings=True)
print(md)
Конвертация в Markdown в PDF Oxide встроенная, поддерживает обнаружение заголовков, сохраняет структуру таблиц и работает с той же скоростью, что и извлечение простого текста.
Конвертация в HTML
PyMuPDF: Нет встроенного вывода HTML.
pypdf: Нет вывода HTML.
PDF Oxide:
from pdf_oxide import PdfDocument
doc = PdfDocument("paper.pdf")
html = doc.to_html(0)
print(html)
Поля форм
Все три библиотеки поддерживают чтение и запись полей форм (AcroForm).
PyMuPDF:
import fitz
doc = fitz.open("form.pdf")
page = doc[0]
for widget in page.widgets():
print(f"{widget.field_name}: {widget.field_value}")
pypdf:
from pypdf import PdfReader
reader = PdfReader("form.pdf")
fields = reader.get_fields()
for name, field in fields.items():
print(f"{name}: {field.get('/V', '')}")
PDF Oxide:
from pdf_oxide import PdfDocument
doc = PdfDocument("form.pdf")
fields = doc.get_form_fields()
for field in fields:
print(f"{field.name}: {field.value}")
Важное отличие: PDF Oxide поддерживает XFA-формы (XML Forms Architecture), которые используются во многих государственных и корпоративных PDF-формах. Ни PyMuPDF, ни pypdf не обрабатывают данные XFA-форм.
Извлечение изображений
PyMuPDF:
import fitz
doc = fitz.open("report.pdf")
page = doc[0]
for i, img in enumerate(page.get_images()):
xref = img[0]
base_image = doc.extract_image(xref)
with open(f"image_{i}.{base_image['ext']}", "wb") as f:
f.write(base_image["image"])
pypdf:
from pypdf import PdfReader
reader = PdfReader("report.pdf")
page = reader.pages[0]
for i, image in enumerate(page.images):
with open(f"image_{i}.{image.name.split('.')[-1]}", "wb") as f:
f.write(image.data)
PDF Oxide:
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
images = doc.extract_image_bytes(0)
for i, img in enumerate(images):
with open(f"image_{i}.{img['format']}", "wb") as f:
f.write(img["data"])
Все три обрабатывают извлечение встроенных изображений. Подход PyMuPDF требует двухшагового поиска через xref. pypdf и PDF Oxide предлагают более лаконичные API.
Рендеринг
PyMuPDF может рендерить страницы PDF в изображения (PNG, JPEG), используя движок рендеринга MuPDF. pypdf не может рендерить страницы. PDF Oxide включает встроенный движок рендеринга.
OCR
PyMuPDF интегрируется с Tesseract для OCR отсканированных PDF. pypdf не поддерживает OCR. PDF Oxide имеет встроенный OCR через PaddleOCR без внешних системных зависимостей.
Создание PDF
PyMuPDF может создавать PDF, но требует ручного размещения текста, изображений и фигур на страницах — нет высокоуровневого API для создания PDF из структурированного контента.
pypdf не может создавать PDF с нуля. Может объединять, разделять и модифицировать существующие PDF, но для создания нужна отдельная библиотека вроде reportlab или fpdf2.
PDF Oxide может создавать PDF из Markdown или HTML:
from pdf_oxide import Pdf
pdf = Pdf.from_markdown("# Invoice\n\n| Item | Price |\n|------|-------|\n| Widget | $9.99 |")
pdf.save("invoice.pdf")
Шифрование
Все три библиотеки поддерживают чтение зашифрованных PDF и запись зашифрованных файлов.
PyMuPDF:
import fitz
doc = fitz.open("encrypted.pdf")
doc.authenticate("password")
text = doc[0].get_text()
pypdf:
from pypdf import PdfReader
reader = PdfReader("encrypted.pdf")
reader.decrypt("password")
text = reader.pages[0].extract_text()
PDF Oxide:
from pdf_oxide import PdfDocument
doc = PdfDocument("encrypted.pdf", password="password")
text = doc.extract_text(0)
Обзор возможностей
| Возможность | PyMuPDF | pypdf | PDF Oxide |
|---|---|---|---|
| Извлечение текста | Да | Да | Да |
| Позиции символов | Да | Частично | Да |
| Извлечение изображений | Да | Да | Да |
| Поля форм (AcroForm) | Чтение + запись | Чтение + запись | Чтение + запись |
| XFA-формы | Нет | Нет | Да |
| Создание PDF | Ручное | Нет | Markdown/HTML |
| Вывод в Markdown | Нет (pymupdf4llm) | Нет | Встроенный |
| Вывод в HTML | Нет | Нет | Встроенный |
| Рендеринг | Да | Нет | Да |
| OCR | Tesseract | Нет | Встроенный (PaddleOCR) |
| Поиск | Да | Нет | Regex + пространственный |
| Шифрование | Чтение + запись | Чтение + запись | Чтение + запись |
| Валидация PDF/A | Нет | Нет | Да |
| Экспорт SVG | Да | Нет | Нет |
| Объединение/разделение | Да | Да | Да |
Когда выбирать какую библиотеку
Выберите pypdf, если:
- Вам нужно решение на чистом Python без компилируемых C- или Rust-расширений
- Вы выполняете простые манипуляции с PDF (объединение, разделение, поворот, шифрование/расшифрование)
- Скорость не критична для вашего сценария
- Нужен минимальный размер установки (~1 МБ)
- Нужна широкая поддержка версий Python (3.6+)
Выберите PyMuPDF, если:
- У вас уже есть коммерческая лицензия MuPDF от Artifex
- Вам нужен экспорт SVG из страниц PDF
- Ваш проект уже лицензирован под AGPL-3.0
- Вы зависите от конкретного поведения рендеринга MuPDF
Выберите PDF Oxide, если:
- Нужна максимальная скорость извлечения текста (в 5.8 раз быстрее PyMuPDF, в 15 раз быстрее pypdf)
- Нужна MIT-лицензия для коммерческого или закрытого использования
- Нужен встроенный вывод в Markdown или HTML для LLM/RAG-пайплайнов
- Нужна поддержка XFA-форм
- Нужен встроенный OCR без внешних системных зависимостей
- Нужна 100% надёжность на валидных PDF
Установка
# PyMuPDF
pip install pymupdf
# pypdf
pip install pypdf
# PDF Oxide
pip install pdf_oxide
Все три доступны через pip. PyMuPDF поставляется с wheel-пакетом ~20 МБ с встроенным MuPDF. pypdf — чистый Python ~1 МБ. PDF Oxide поставляется с предсобранными wheel-пакетами (~5 МБ) для Linux (x86_64, aarch64), macOS (x86_64, arm64) и Windows (x86_64).
Вердикт
Если вы выбираете между PyMuPDF и pypdf, вы выбираете между скоростью и свободой лицензирования. PDF Oxide даёт вам и то, и другое — быстрее PyMuPDF, свободнее pypdf, с возможностями, которых нет ни у одной из них.
| Что для вас важно | Лучший выбор |
|---|---|
| Максимальная скорость | PDF Oxide (0.8 мс) |
| Разрешительная лицензия | PDF Oxide (MIT) или pypdf (BSD) |
| Скорость + разрешительная лицензия | PDF Oxide — единственный вариант |
| Вывод в Markdown/HTML | PDF Oxide — встроенный |
| XFA-формы | PDF Oxide — единственная поддерживающая библиотека |
| 100% надёжность | PDF Oxide — 100% успешность |
| OCR без Tesseract | PDF Oxide — встроенный PaddleOCR |
| Экспорт SVG | PyMuPDF |
| Чистый Python, без бинарников | pypdf |
Начните за 10 секунд:
pip install pdf_oxide
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
text = doc.extract_text(0)
Связанные страницы
- PDF Oxide vs PyMuPDF — детальное сравнение
- PDF Oxide vs pypdf — детальное сравнение
- Сравнение с Python-библиотеками — полное сравнение экосистемы
- Benchmark производительности — методология и результаты