Skip to content

Python Office 库 — 快速上手

office_oxide 是 Office 文档处理领域最快的 Python 库。纯 Rust 内核,API 遵循 Python 风格,零运行时依赖。读取 DOCX、XLSX、PPTX(以及旧版 DOC、XLS、PPT)只需不到 1 毫秒 — 比 python-docxopenpyxlpython-pptx 快 8 到 100 倍。

安装

pip install office-oxide

为 CPython 3.8 至 3.14 提供 Linux、macOS、Windows 的 wheel。PyPI 包名是 office-oxide(连字符),导入名是 office_oxide(下划线)。

读取文档

from office_oxide import Document

with Document.open("report.docx") as doc:
    print(doc.plain_text())

或使用一次性辅助函数:

import office_oxide
print(office_oxide.extract_text("report.docx"))

核心 API

Document.open 根据文件扩展名识别格式(再用魔术字节复核),接受 strbytes 或任何 os.PathLike。建议作为上下文管理器使用,以便确定性地释放底层内存。

from pathlib import Path
from office_oxide import Document

with Document.open(Path("data/deck.pptx")) as doc:
    print(doc.format)           # "pptx"
    print(doc.plain_text())     # str
    print(doc.to_markdown())    # str — GitHub Flavored Markdown
    print(doc.to_html())        # str — 语义化 HTML
    ir = doc.to_ir()            # 嵌套字典(DocumentIR)

    doc.save_as("deck.docx")    # 旧版 PPT → PPTX 也支持

文件不在磁盘上时,可从原始字节打开:

data = open("report.xlsx", "rb").read()
with Document.from_bytes(data, "xlsx") as doc:
    print(doc.plain_text())

模块级快捷方法:

import office_oxide
office_oxide.extract_text("file.docx")   # → str
office_oxide.to_markdown("file.pptx")    # → str
office_oxide.to_html("file.xlsx")        # → str
office_oxide.version()                   # → "0.1.0"

编辑

EditableDocument 在保存时保留所有未修改的 OPC 部件(图片、图表、样式、关系)。仅支持 DOCX、XLSX、PPTX。

from office_oxide import EditableDocument

with EditableDocument.open("template.docx") as ed:
    n = ed.replace_text("{{name}}", "Alice")
    print(f"替换了 {n} 处")
    ed.save("out.docx")

在 DOCX / PPTX 中替换文本

from office_oxide import EditableDocument

with EditableDocument.open("slides.pptx") as ed:
    ed.replace_text("Q3", "Q4")
    ed.replace_text("2024", "2025")
    ed.save("slides_q4.pptx")

replace_text 在 DOCX 中遍历 <w:t> 元素,在 PPTX 中遍历每张幻灯片的 <a:t>,并返回替换次数。

写入 XLSX 单元格

from office_oxide import EditableDocument

with EditableDocument.open("budget.xlsx") as ed:
    ed.set_cell(0, "A1", "Total")     # 字符串
    ed.set_cell(0, "B1", 42.5)        # 数字(int 也行)
    ed.set_cell(0, "C1", True)        # 布尔值
    ed.set_cell(0, "D1", None)        # 清空
    ed.save("budget.xlsx")

sheet_index 从 0 开始;cell_ref 使用标准电子表格记号(A1AA12)。

格式无关的 IR

doc.to_ir() 返回与 Rust DocumentIR 对应的嵌套 dict — 由标题、段落、表格、列表、图片组成的若干 section。适合接入处理流水线或为 LLM 提供结构化上下文。

ir = doc.to_ir()
for section in ir["sections"]:
    print(section.get("title"))
    for el in section["elements"]:
        kind = el["kind"]   # "Heading" | "Paragraph" | "Table" | "List" | ...

基于字节流的管道

from_bytes 在无服务器、流式工作流中可省去临时文件:

import requests
from office_oxide import Document

data = requests.get("https://example.com/doc.docx").content
with Document.from_bytes(data, "docx") as doc:
    print(doc.to_markdown())

旧版格式

DOC、XLS、PPT 走相同的 API。扩展名识别会自动选择旧版 CFB 解析器;save_as 透明地输出现代 OOXML:

with Document.open("legacy.doc") as doc:
    print(doc.plain_text())
    doc.save_as("legacy.docx")     # 一行完成 DOC → DOCX

错误处理

解析与 IO 失败会抛出 OfficeOxideErrorsave_as 的 IO 失败被 IOError 包装。

from office_oxide import Document, OfficeOxideError

try:
    with Document.open("weird.file") as doc:
        print(doc.plain_text())
except OfficeOxideError as e:
    print(f"office_oxide 失败: {e}")
except FileNotFoundError:
    print("文件不存在")

故障排查

症状 原因
OfficeOxideError: unsupported format: "" 路径没有扩展名 — 改用 Document.from_bytes(data, "docx")
RuntimeError: Document is closed 退出 with 后仍持有引用。重新打开句柄。
ImportError: _native wheel 与你的平台不匹配。pip install --force-reinstall office-oxide
旧版 DOC 显示乱码 文件可能已加密(Word 97 RC4)。office_oxide 不支持解密 — 请先用 LibreOffice 解密。
Windows 上的 Unicode 问题 pathlib.Path 而不是字节路径;Document.open 会处理平台编码。

相关链接