Skip to content

PyMuPDF 与 pypdf——该选哪个 Python PDF 库?

PyMuPDF 和 pypdf 是最流行的两个 Python PDF 库,但两者都有明显的取舍。PyMuPDF 速度快,却被 AGPL-3.0 许可证所束缚。pypdf 采用宽松许可证,但慢了 15 倍。本页将两者正面对比——并说明为何 PDF Oxide 比两者都更合适

简短答案: PDF Oxide 比 PyMuPDF 快 5.8 倍,比 pypdf 快 15 倍,采用 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
通过率(3,830 个 PDF) 99.3% 98.4% 100%
文本提取 支持 支持 支持
字符位置 支持 部分支持 支持
图像提取 支持 支持 支持
表单字段 读取 + 写入 读取 + 写入 读取 + 写入
PDF 创建 支持 有限(仅合并) 支持(Markdown/HTML)
Markdown 输出 不支持 不支持 支持
HTML 输出 不支持 不支持 支持
渲染 支持 不支持 支持
OCR Tesseract 不支持 内置(PaddleOCR)
安装体积 约 20 MB 约 1 MB 约 5 MB
加密 读取 + 写入 读取 + 写入 读取 + 写入
搜索 支持 不支持 正则 + 空间
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,而 MuPDF 采用 AGPL-3.0 许可证。这是一种强 Copyleft 许可证。如果你分发任何使用 PyMuPDF 的软件——包括 SaaS 应用、Docker 容器、Web 服务、桌面应用或 CLI 工具——你的整个应用都必须以 AGPL-3.0 发布。也就是说,要在相同许可证下公开你的全部源代码。

替代方案是向 MuPDF 背后的公司 Artifex 购买商业许可证。Artifex 并不公开定价;你必须联系其销售团队获取报价。商业许可证通常按年计费,并按应用定价。

AGPL 在以下情况会影响你:

  • 你交付的产品包含 PyMuPDF(桌面应用、移动应用、Electron)
  • 你运营的 SaaS 或 Web 服务使用 PyMuPDF 处理 PDF
  • 你分发的 Docker 镜像中包含 PyMuPDF
  • 你提供的 API 在内部使用了 PyMuPDF

AGPL 在以下情况不会影响你:

  • 你的项目已在与 AGPL 兼容的许可证下开源
  • 你仅将 PyMuPDF 用于从不分发的内部工具

pypdf——BSD-3

pypdf 采用宽松的 BSD 3-Clause 许可证。你可以在商业产品、闭源软件和 SaaS 应用中使用 pypdf,无需任何开源代码的义务。唯一的要求是在再分发时保留版权声明。

PDF Oxide——MIT

PDF Oxide 采用 MIT 许可证——最宽松的常见开源许可证。你可以在任何场景下(商业、专有、SaaS、开源)使用它,除了附带许可证文本外没有任何限制。

许可证小结

使用场景 PyMuPDF (AGPL) pypdf (BSD) PDF Oxide (MIT)
商业产品 需要许可证 可以 可以
闭源 SaaS 需要许可证 可以 可以
Docker 分发 需要许可证 可以 可以
内部工具 可以 可以 可以
开源(AGPL 兼容) 可以 可以 可以
开源(MIT/BSD/Apache) 不可以 可以 可以

对于许可证合规很重要的商业项目,pypdf 和 PDF Oxide 都是安全的选择。PyMuPDF 要么需要将你的应用开源,要么需要购买商业许可证。

速度基准测试

所有基准测试都在同一个 3,830 个 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 比 pypdf 快 2.6x,因为它将解析委托给了 MuPDF 的 C 引擎。pypdf 全部用纯 Python 完成——解析、字体解码、文本组装——这意味着每一项操作都要承担解释器的开销。

PDF Oxide 比两者都快,因为它的 Rust 内核通过 PyO3 原生处理所有 PDF 解析、字体解码和文本布局,只有最终结果才跨越 Python 边界。没有子进程开销,没有通过 ctypes 桥接的 C 库,也没有解释器瓶颈。

可靠性

通过的有效 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 而无任何失败。

在完整的 3,830 个文件语料库中,那 7 个未通过的文件是故意损坏的测试夹具(缺失 PDF 文件头、被模糊测试破坏的目录、无效的 xref 流),对所有库都已从通过率计算中排除。

这在实践中意味着什么

对于每天处理数千个 PDF 的流水线而言,PyMuPDF 99.3% 的通过率意味着每 1,000 个文档大约有 7 次失败。pypdf 的 98.4% 意味着每 1,000 个约有 16 次失败。这些文档你需要用回退逻辑、人工审核来处理,或者干脆当作丢失的数据接受。

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 可以用,但比 PDF Oxide 内置的 Markdown 转换慢 69x(平均 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)

PDF Oxide 的 Markdown 转换是内置的,能处理标题检测,保留表格结构,并以与纯文本提取相同的速度运行。

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 可以使用 MuPDF 的渲染引擎将 PDF 页面渲染为图像(PNG、JPEG)。pypdf 完全无法渲染页面。PDF Oxide 内置了一个渲染引擎。

OCR

PyMuPDF 集成 Tesseract,用于对扫描版 PDF 进行 OCR。pypdf 没有 OCR 支持。PDF Oxide 通过 PaddleOCR 内置了 OCR,无需任何外部系统依赖。

PDF 创建

PyMuPDF 可以创建 PDF,但需要在页面上手动放置文本、图像和形状——没有用于从结构化内容创建 PDF 的高级 API。

pypdf 无法从零创建 PDF。它可以合并、拆分和修改现有 PDF,但若要创建,你需要 reportlab 或 fpdf2 这样的单独库。

PDF Oxide 可以从 Markdown 或 HTML 创建 PDF:

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)
搜索 支持 不支持 正则 + 空间
加密 读取 + 写入 读取 + 写入 读取 + 写入
PDF/A 校验 不支持 不支持 支持
SVG 导出 支持 不支持 不支持
合并/拆分 支持 支持 支持

何时该选哪个库

选择 pypdf,如果:

  • 你需要一个纯 Python 方案,不含编译的 C 或 Rust 扩展
  • 你在做简单的 PDF 操作(合并、拆分、旋转、加密/解密)
  • 速度对你的用例并不关键
  • 你想要尽可能小的安装体积(约 1 MB)
  • 你需要广泛的 Python 版本支持(3.6+)

选择 PyMuPDF,如果:

  • 你已经拥有来自 Artifex 的 MuPDF 商业许可证
  • 你需要从 PDF 页面导出 SVG
  • 你的项目已在 AGPL-3.0 下授权
  • 你依赖 MuPDF 特有的渲染行为

选择 PDF Oxide,如果:

  • 你需要最高的文本提取速度(比 PyMuPDF 快 5.8x,比 pypdf 快 15x)
  • 你想要 MIT 许可证以用于商业或闭源用途
  • 你需要为 LLM/RAG 流水线提供内置的 Markdown 或 HTML 输出
  • 你需要 XFA 表单支持
  • 你想要无需外部系统依赖的内置 OCR
  • 你想要在有效 PDF 上达到 100% 的可靠性

安装

# PyMuPDF
pip install pymupdf

# pypdf
pip install pypdf

# PDF Oxide
pip install pdf_oxide

三者都可通过 pip 获取。PyMuPDF 提供一个约 20 MB 的 wheel,内含打包的 MuPDF。pypdf 是约 1 MB 的纯 Python。PDF Oxide 为 Linux(x86_64、aarch64)、macOS(x86_64、arm64)和 Windows(x86_64)提供预构建的 wheel(约 5 MB)。

结论

如果你在 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% 通过率
无需 Tesseract 的 OCR 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)

相关页面