Skip to content

PyMuPDF против pypdf — какую Python-библиотеку для PDF выбрать?

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.6ms 12.1ms 0.8ms
Время извлечения p99 28ms 97ms 9ms
Доля успешных (3830 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 против BSD против MIT

Различие в лицензировании между PyMuPDF и pypdf часто становится решающим фактором для команд, выбирающих между ними.

PyMuPDF — AGPL-3.0

PyMuPDF оборачивает MuPDF, который лицензирован под AGPL-3.0. Это сильная копилефт-лицензия. Если вы распространяете любое программное обеспечение, использующее 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 — самой свободной из распространённых лицензий открытого ПО. Используйте её в любом контексте (коммерческом, проприетарном, SaaS, открытом) без каких-либо ограничений, кроме включения текста лицензии.

Итоги по лицензированию

Сценарий использования PyMuPDF (AGPL) pypdf (BSD) PDF Oxide (MIT)
Коммерческий продукт Требуется лицензия Да Да
SaaS с закрытым кодом Требуется лицензия Да Да
Распространение через Docker Требуется лицензия Да Да
Внутренние инструменты Да Да Да
Открытый код (совместимый с AGPL) Да Да Да
Открытый код (MIT/BSD/Apache) Нет Да Да

Для коммерческих проектов, где важно соблюдение лицензий, и pypdf, и PDF Oxide — безопасный выбор. PyMuPDF требует либо открытия исходного кода вашего приложения, либо покупки коммерческой лицензии.

Бенчмарки скорости

Все бенчмарки выполнялись на одном и том же корпусе из 3830 PDF — трёх независимых, публично доступных наборах тестов (veraPDF, Mozilla pdf.js, DARPA SafeDocs), охватывающих каждую версию спецификации PDF (1.0–2.0), зашифрованные файлы, кодировки CJK, сложные макеты и некорректные документы.

Скорость извлечения текста

Библиотека Среднее p99 Относительно PDF Oxide
PDF Oxide 0.8ms 9ms 1x
PyMuPDF 4.6ms 28ms в 5,8x медленнее
pypdf 12.1ms 97ms в 15,1x медленнее

PyMuPDF в 2,6x быстрее 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 обрабатывает все 3823 валидных PDF без единого сбоя.

7 непройденных файлов в полном корпусе из 3830 файлов — это намеренно повреждённые тестовые фикстуры (отсутствующий заголовок PDF, испорченные фаззингом каталоги, некорректные потоки xref), и они исключены из расчёта доли успешных для всех библиотек.

Что это означает на практике

Для конвейера, обрабатывающего тысячи PDF в день, доля успешных PyMuPDF в 99,3% означает примерно 7 сбоев на 1000 документов. 98,4% у pypdf — это 16 сбоев на 1000. Это документы, которые вам нужно обрабатывать с помощью резервной логики, ручной проверки или просто принять как потерянные данные.

Доля успешных PDF Oxide в 100% на тестовом корпусе означает меньше пограничных случаев, с которыми придётся иметь дело в продакшене.

Сравнение функций

Извлечение текста

Все три библиотеки поддерживают базовое извлечение текста. Стили 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 использует паттерн reader/pages. PDF Oxide использует индексы страниц напрямую.

Для извлечения на уровне символов (позиции, размеры шрифта, ограничивающие рамки) PyMuPDF предоставляет get_text("dict"), который возвращает вложенную структуру словаря. pypdf предлагает частичные данные о позициях символов. PDF Oxide предоставляет extract_chars() с ограничивающими рамками для каждого символа и метаданными шрифта.

Преобразование в Markdown

Это существенное отличие. Многим конвейерам LLM и RAG нужен вывод PDF в Markdown.

PyMuPDF:

# PyMuPDF has no built-in Markdown conversion.
# You need pymupdf4llm, a separate package:
import pymupdf4llm

md = pymupdf4llm.to_markdown("paper.pdf")

pymupdf4llm работает, но в 69x медленнее встроенного преобразования в Markdown в PDF Oxide (в среднем 55.5ms против 0.8ms). К тому же это отдельная зависимость со своим циклом сопровождения.

pypdf:

# pypdf has no Markdown conversion.
# You would need an external tool chain (e.g., extract text,
# then use a separate library to structure it as 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,8x быстрее PyMuPDF, в 15x быстрее 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 поставляет колесо размером ~20 МБ с встроенным MuPDF. pypdf — чистый Python размером ~1 МБ. PDF Oxide поставляет готовые колёса (~5 МБ) для Linux (x86_64, aarch64), macOS (x86_64, arm64) и Windows (x86_64).

Вердикт

Если вы выбираете между PyMuPDF и pypdf, вы выбираете между скоростью и свободой лицензирования. PDF Oxide даёт и то, и другое — быстрее PyMuPDF, свободнее pypdf, с функциями, которых нет ни в одной из них.

Что для вас важно Лучший выбор
Максимальная скорость PDF Oxide (0.8ms)
Свободная лицензия 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)

Связанные страницы