python-calamine(と calamine)からの移行
calamine は定評ある Rust 製 XLSX/XLS リーダー、python-calamine はその Python バインディングです。どちらもスプレッドシートのみに特化しています。
Office Oxide は XLSX で python-calamine より 2.8 倍高速(1,802 ファイルで平均 5.0 ms 対 13.9 ms)、最高のパス率(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 は公開する; Office Oxide の IR はしない)
インストール(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)
1 枚のシートを行として読む
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 は EditableDocument 経由で XLSX セルを書けます:
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 ms | 40 ms | 97.8% |
| python-calamine | 13.9 ms | 183 ms | 96.6% |
| openpyxl | 94.5 ms | 698 ms | 96.2% |
| ライブラリ | XLS 平均 | p99 | 通過率 |
|---|---|---|---|
| office_oxide | 2.8 ms | 75 ms | 99.2% |
| python-calamine | 9.0 ms | 96 ms | 90.7% |
異なる点
calamine はセルごとに型付き Data enum(Int、Float、String、Bool、DateTime、Empty、Error)を返します。Office Oxide の IR は文字列に畳み込みます; 型付きセルアクセスにはフォーマット固有のアクセサを使います:
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"
関連項目
- openpyxl からの移行 — openpyxl ユーザー向け
- xlrd からの移行 — レガシー
.xlsユーザー向け - パフォーマンスベンチマーク