Миграция с xlrd
xlrd был стандартной Python-библиотекой для чтения устаревших .xls (Excel 97–2003). В версии 2.0 (2020) он убрал поддержку .xls и рекомендует мигрировать. Обходные пути сообщества — пин xlrd<2.0, вызов LibreOffice, переход на python-calamine — у каждого свои оговорки.
Office Oxide читает .xls напрямую, в 13 раз быстрее последнего релиза xlrd с поддержкой .xls, с более высокой долей успеха. Бонусом можно конвертировать .xls → .xlsx одной строкой.
Когда мигрировать
Переходите, если что-то из этого про вас:
- Вы всё ещё на
xlrd<2.0и хотите поддерживаемую библиотеку - Нужны
.xlsи.xlsxиз одной библиотеки - Хотите один раз мигрировать корпус в
.xlsxи перестать возиться с устаревшим форматом - Нужны также
.doc,.ppt,.docxили.pptx— покрывается той же установкой
Установка
pip uninstall xlrd
pip install office-oxide
Сравнительная шпаргалка
Открыть .xls
xlrd
import xlrd
book = xlrd.open_workbook("legacy.xls")
sheet = book.sheet_by_index(0)
office_oxide
from office_oxide import Document
with Document.open("legacy.xls") as doc:
xls = doc.as_xls()
sheet = xls.sheets()[0]
Итерация по ячейкам
xlrd
for row in range(sheet.nrows):
for col in range(sheet.ncols):
print(sheet.cell_value(row, col))
office_oxide
for cell in sheet.cells():
print(cell.address(), cell.value())
Прочитать все ячейки как таблицу (самый частый случай)
xlrd
import xlrd
book = xlrd.open_workbook("legacy.xls")
sheet = book.sheet_by_index(0)
rows = [
[sheet.cell_value(r, c) for c in range(sheet.ncols)]
for r in range(sheet.nrows)
]
office_oxide
from office_oxide import Document
with Document.open("legacy.xls") as doc:
ir = doc.to_ir()
# Первый лист → первая секция → первая таблица
table = next(el for el in ir["sections"][0]["elements"] if el["kind"] == "Table")
rows = table["rows"]
Имена листов
xlrd
book = xlrd.open_workbook("legacy.xls")
print(book.sheet_names())
office_oxide
with Document.open("legacy.xls") as doc:
print([s.name() for s in doc.as_xls().sheets()])
Конвертация .xls → .xlsx одной строкой
Если ваша обвязка уже понимает .xlsx, самая чистая миграция — один раз конвертировать корпус и больше не трогать .xls:
from office_oxide import Document
with Document.open("legacy.xls") as doc:
doc.save_as("modern.xlsx")
Для целого каталога:
from pathlib import Path
from office_oxide import Document
for src in Path("legacy").rglob("*.xls"):
dst = src.with_suffix(".xlsx")
with Document.open(src) as doc:
doc.save_as(dst)
Производительность
| Библиотека | .xls Среднее |
p99 | Доля успеха |
|---|---|---|---|
| office_oxide | 2,8 мс | 75 мс | 99,2% |
| python-calamine | 9,0 мс | 96 мс | 90,7% |
| xlrd | 36,6 мс | 503 мс | 93,1% |
Office Oxide в 13 раз быстрее xlrd и имеет долю успеха на 6,1 процентного пункта выше.
Что теряется
Выражения формул xlrd, именованные диапазоны и кэши общих формул не пробрасываются через IR. Кэшированные результаты формул сохраняются — именно это обычно нужно обвязке. Для самих выражений формул спускайтесь в формат-специфичный модуль xls либо конвертируйте в .xlsx и используйте xlsx.
См. также
- Миграция с openpyxl — для
.xlsx - Конвертация: устаревшие → OOXML — что делает
save_as - Бенчмарки производительности