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)
단일 시트를 행 목록으로 읽기
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사용자용 - 성능 벤치마크