Skip to content

Міграція з python-calamine (і calamine)

calamine — високоповажний Rust-рідер XLSX/XLS; python-calamine — його Python-біндинг. Обидва зосереджені виключно на таблицях.

Office Oxide у 2,8 рази швидший за python-calamine на XLSX (5,0 мс проти 13,9 мс у середньому на 1 802 файлах), з найвищою часткою успіху (97,8% проти 96,6%). Він також додає повну підтримку DOCX, PPTX та застарілих DOC/PPT — форматів, які calamine взагалі не читає.

Коли мігрувати

Перемикайтеся, якщо щось із цього про вас:

  • Потрібні також .docx / .pptx / .doc / .ppt (calamine — лише XLSX/XLS)
  • Хочете ширший набір можливостей: вивід у Markdown / HTML, структурований IR, шаблонізація через EditableDocument
  • Частка успіху важливіша за незначну перевагу calamine за продуктивністю в окремих сценаріях
  • Ви на Python-біндингу і хочете менше конверсій через FFI

Залишайтеся на calamine, якщо:

  • Ви читаєте тільки .xlsx і .xls
  • Залежите від специфічних для calamine API (Reader::with_header_row, worksheet_range_at тощо)
  • Потрібні вирази формул (calamine їх надає; IR Office Oxide — ні)

Встановлення (Python)

pip uninstall python-calamine
pip install office-oxide

Встановлення (Rust)

# Cargo.toml
[dependencies]
# Замінити:
#   calamine = "0.30"
office_oxide = "0.1.0"

Порівняльна шпаргалка — Python

Відкрити робочу книгу

python-calamine

from python_calamine import CalamineWorkbook

wb = CalamineWorkbook.from_path("budget.xlsx")

office_oxide

from office_oxide import Document

with Document.open("budget.xlsx") as doc:
    ...

Ітерація по аркушах

python-calamine

for name in wb.sheet_names:
    sheet = wb.get_sheet_by_name(name)
    for row in sheet.to_python():
        print(row)

office_oxide

with Document.open("budget.xlsx") as doc:
    ir = doc.to_ir()

for section in ir["sections"]:
    print(f"# {section.get('title')}")
    for el in section["elements"]:
        if el["kind"] == "Table":
            for row in el["rows"]:
                print(row)

Прочитати один аркуш як рядки

python-calamine

sheet = wb.get_sheet_by_name("Q4")
rows = sheet.to_python()

office_oxide

with Document.open("budget.xlsx") as doc:
    table = next(
        el for section in doc.to_ir()["sections"]
        if section.get("title") == "Q4"
        for el in section["elements"] if el["kind"] == "Table"
    )
    rows = table["rows"]

Більш прямий шлях:

with Document.open("budget.xlsx") as doc:
    sheet = doc.as_xlsx().sheet("Q4")
    rows = sheet.rows()    # list[list[str]]

Імена аркушів

python-calamine

print(wb.sheet_names)

office_oxide

with Document.open("budget.xlsx") as doc:
    print([s.name() for s in doc.as_xlsx().sheets()])

Порівняльна шпаргалка — Rust

Відкрити й проітерувати

calamine

use calamine::{open_workbook, Xlsx, Reader};

let mut wb: Xlsx<_> = open_workbook("budget.xlsx")?;
for sheet_name in wb.sheet_names() {
    if let Ok(range) = wb.worksheet_range(&sheet_name) {
        for row in range.rows() {
            println!("{row:?}");
        }
    }
}

office_oxide

use office_oxide::Document;

let doc = Document::open("budget.xlsx")?;
if let Some(xlsx) = doc.as_xlsx() {
    for sheet in xlsx.sheets() {
        for cell in sheet.cells() {
            println!("{}: {:?}", cell.address(), cell.value());
        }
    }
}

Формат-незалежний IR (у calamine еквівалента немає)

let doc = Document::open("budget.xlsx")?;
let ir = doc.to_ir();
serde_json::to_writer(std::io::stdout(), &ir)?;

Форма виходу така сама, як із .docx чи .pptx — корисно, коли даунстрім-споживачам не треба знати вихідний формат.

Записи в XLSX

calamine — лише для читання. Office Oxide пише клітинки XLSX через EditableDocument:

from office_oxide import EditableDocument

with EditableDocument.open("budget.xlsx") as ed:
    ed.set_cell(0, "B5", 42_000)
    ed.save("budget.xlsx")

Для повноцінної збірки XLSX спускайтеся в xlsx::create::XlsxBuilder або використовуйте umya-spreadsheet / rust_xlsxwriter.

Продуктивність

Бібліотека XLSX Середнє p99 Частка успіху
office_oxide 5,0 мс 40 мс 97,8%
python-calamine 13,9 мс 183 мс 96,6%
openpyxl 94,5 мс 698 мс 96,2%
Бібліотека XLS Середнє p99 Частка успіху
office_oxide 2,8 мс 75 мс 99,2%
python-calamine 9,0 мс 96 мс 90,7%

Чим відрізняються

calamine повертає типізований Data-enum на клітинку (Int, Float, String, Bool, DateTime, Empty, Error). IR Office Oxide згортає значення в рядки; для типізованого доступу до клітинок використовуйте формат-специфічний аксесор:

with Document.open("budget.xlsx") as doc:
    for sheet in doc.as_xlsx().sheets():
        for cell in sheet.cells():
            print(cell.value(), cell.value_type())   # value_type: "string" | "number" | "boolean" | "empty"

Див. також