Як прочитати сотні тисяч рядків в Excel, не заповнюючи пам'ять одночасно

У цій статті представлено рішення для захисного програмування, включаючи відновлення розмірності, безпеку ресурсів і перевірку цілісності для вирішення проблем переповнення пам’яті та скорочення даних під час читання великих файлів у режимі openpyxl read_only. Роз’яснено граничні умови та стандарти перевірки вручну, а також надано конкретні точки підключення для двомовного порівняння та прийняття в поєднанні з OmniDoc.

Як прочитати велику таблицю, не витрачаючи пам'ять? Ця стаття призначена для розробників і команд обробки даних, яким потрібно використовувати Python для обробки сотень тисяч рядків Excel. Після прочитання ви дізнаєтесь про причини збільшення обсягу файлової пам’яті та скорочення даних, а також про те, як використовувати режим openpyxl лише для читання, відновлення розмірності та звільнення ресурсу, щоб запобігти цим проблемам.

У прикладах у цій статті використовуються синтетичні зразки. Код було перевірено з прикладами в ізольованому середовищі, але це не є гарантією всіх реальних файлів або продуктивності продукту. Перед обробкою важливих документів збережіть оригінали та перегляньте їх відповідно до меж і пунктів прийняття в тексті.

Як прочитати велику таблицю без розриву пам'яті? Висновок одним реченням

Використовуйте read_only=True для потокового читання великих файлів і явного закриття книги після читання; якщо кількість прочитаних рядків явно замала, спочатку перевірте інформацію про розмір файлу, а потім поєднайте її з ручним порівнянням, щоб підтвердити, що дані повні.

ваша ситуаціяРекомендовані практикипричина
Відкриття великих файлів у режимі за замовчуванням швидко виснажує пам’ятьНатомість використовуйте потокове читання read_only=TrueРежим за замовчуванням завантажує всі об’єкти комірки та їхні стилі, коментарі та інші метадані в пам’ять одночасно
Він читає лише перші кілька тисяч рядків і закінчується без повідомлення про помилку.Використовуйте reset_dimensions(), щоб виправити та перечитати, а також встановити мінімальну кількість рядків і нижній рядокРежим лише для читання довіряє dimensions, оголошеному у файлі. Якщо він написаний неправильно, ітератор завершиться раніше.
Сценарій ETL, який циклично переглядає кілька файлівВиклик wb.close() явно в блоці finallyНезакриття призведе до витоку дескриптора файлу, що зрештою запустить OSError: Too many open files
Дані для використання в офіційних процесахЕкспортуйте журнали у вихідну систему та виконайте перевірку вибірки вручнуВиконання коду не означає, що дані правильні

Пряма причина вибуху пам’яті або скорочення даних під час читання сотень тисяч рядків у Excel

Коли ви використовуєте load_workbook('huge.xlsx') для відкриття таблиці з півмільйона рядків, програма може використати 8 ГБ пам’яті за кілька секунд або завершити роботу після прочитання лише перших 1000 рядків.

Причина першого полягає в тому, що режим за замовчуванням завантажує всі об’єкти комірки та їхні стилі, коментарі та інші метадані в пам’ять одночасно. Останнє пояснюється тим, що в режимі read_only=True openpyxl повністю довіряє атрибуту dimensions, оголошеному всередині файлу, щоб забезпечити продуктивність.

Якщо система, яка створила файл (наприклад, якийсь старий модуль експорту ERP або нестандартна бібліотека Python), записує ці метадані неправильно, ітератор припинить роботу передчасно, не викидаючи жодних винятків. Це не помилка коду, а розрив між специфікаціями формату та даними реального світу, який потрібно подолати за допомогою захисного програмування.

Правильний метод відкриття та звільнення ресурсу режиму read_only

read_only=True — це основний шлях для обробки великих файлів, але він змінює керування життєвим циклом об’єктів. Звичайні робочі книги автоматично звільняють ресурси під час збирання сміття, тоді як робочі книги, призначені лише для читання, зберігають посилання на потік файлів ZIP і аналізатор XML у нижній частині та мають явно викликати wb.close(). Щоб отримати офіційні інструкції щодо режиму лише для читання, зверніться до Офіційна документація openpyxl Optimized Modes.

Якщо забути цей крок у сценарії ETL, який циклічно переглядає кілька файлів, це може призвести до витоків дескрипторів файлів, що зрештою запустить OSError: Too many open files. Цей тип помилки часто виявляється після кількох годин роботи, і її надзвичайно важко усунути.

Крім того, режим лише для читання повертає ReadOnlyCell замість стандартного об’єкта Cell. Він не підтримує доступ до таких атрибутів, як стилі та анотації, а також не дозволяє зворотний пошук або зміну значень за допомогою координат. Якщо під час ітерації ви отримаєте інформацію про об’єднану область або встановите колір комірки, ви отримаєте AttributeError. Це обмеження навмисне для підтримки майже постійного відбитка пам’яті.

📊 Основне порівняння

Порівняльний пунктРежим за замовчуваннямread_only Візерунок
Використання пам'ятіЗавантажує всі клітинні об'єкти та метадані одночасно; великі файли легко можуть виснажувати пам'ятьПід час читання потоку використання пам'яті майже постійне
Повернені об'єкти коміркиСтандартний CellReadOnlyCell
Стилі та доступ до коментарівПідтримкаНе підтримується, доступ до нього отримає AttributeError
Змінюйте значення або встановлюйте кольориПідтримкаНемає підтримки
Залежності від файлу dimensionsНе залежнийЗалежність, і якщо ви напишете помилку, ітерація може закінчитися передчасно
Випуск ресурсівАвтоматично скидає відходи під час зборуwb.close() має бути явно закликаний

Приклад синтезу: Відновлення вимірів і ітеративна перевірка безпеки

Наступний код демонструє типовий захисний потік читання. Зверніть увагу, що це приклад синтезу, який використовується для демонстрації логічної структури, а не фактичних результатів обробки виробничих даних. Вам потрібно самостійно підготувати файл input_large.xlsx для запуску цього скрипту, і він має виконуватися в ізольованому середовищі з заблокованими версіями залежностей. Приклад не включає мережеві операції, команди shell або конфіденційні облікові дані.

from openpyxl import load_workbook

# 合成示例:演示read_only模式下的安全读取与维度校验
# 依赖:openpyxl (需在项目requirements中锁定具体版本)
# 注意:需读者自备 input_large.xlsx,本示例不包含真实数据

def safe_read_large_excel(filepath, expected_min_rows=1000):
    """
    安全读取大Excel文件,包含维度修复与完整性校验。
    :param filepath: Excel文件路径
    :param expected_min_rows: 业务预期的最小行数阈值
    :return: 实际读取的行数
    """
    wb = load_workbook(filename=filepath, read_only=True)
    try:
        ws = wb.active
        # 检查并修复可能错误的维度声明
        # calculate_dimension() 可能返回 'A1:A1' 或其他不准确范围
        dim = ws.calculate_dimension()
        if dim == "A1:A1" or not dim:
            # 重置维度以强制扫描实际数据区域
            # 警告:若文件完全无维度信息,此操作可能遍历全表(104万行)
            ws.reset_dimensions()

        row_count = 0
        header = None
        for row in ws.iter_rows(values_only=True):
            if row_count == 0:
                header = row
                assert header is not None and any(v is not None for v in header), \
                    "首行不应为空或全None"
            row_count += 1

            # 模拟业务处理,避免全量加载到内存
            if row_count % 10000 == 0:
                print(f"已处理 {row_count} 行")

        # 校验读取完整性
        assert row_count >= expected_min_rows, \
            f"行数不足: 期望>={expected_min_rows}, 实际={row_count}。请检查源文件或维度设置。"
        return row_count
    finally:
        # 必须显式关闭,防止句柄泄漏
        wb.close()

# 使用示例(需替换为真实文件路径)
# total = safe_read_large_excel("input_large.xlsx", expected_min_rows=50000)

Ключ до цього коду — не саме читання, а три рівні захисту:

  • Скидання розміру: Виправлено оголошення файлу dimensions, щоб ітератор не закінчився занадто рано.
  • Stream Count: Рахуйте рядки під час читання, що полегшує порівняння з очікуваннями.
  • Примусове закриття в finally: Звільняє файлові ресурси незалежно від успішних помилок читання або проміжних помилок.

expected_min_rows — це не стандартний поріг галузі, а бізнес-підсумок, заснований на ваших попередніх знаннях вихідних даних. Якщо фактична кількість рядків менша за це значення, це означає, що файл може бути пошкоджений або відновлення розмірності не вдалося. У такому випадку слід виконувати переривання, а не безмовно приймати неповні дані.

Критерії прийняття та межі ручного перегляду

Правильне виконання коду не означає, що дані правильні. Таблиця нижче перелічена типовими аномаліями, які можуть зустрічатися в реальних проєктах, і способами їх подолання, розрізняючи обсяг покриття автоматизації та сценарії, що потребують ручного втручання.

Спостерігайте за явищемМожливі причиниАвтоматизована обробкаВимоги до ручного перегляду
Кількість прочитаних рядків значно менша, ніж очікувалосяпомилка атрибута розмірівСпробуй перечитати після reset_dimensionsПорівняйте вихідну систему експорту логів і переконайтеся, чи справді лог відсутній
reset_dimensions Час, необхідний після цього, значно збільшивсяФайл не містить інформації про розмірність, що спричиняє повне сканування таблиціВстановіть max_row стратегію завершення ліміту або порожньої лініїОцініть якість генератора файлів і виведіть виправлення вгору по потоку
Деякі клітини мають значення NoneОб'єднані елементи або формули не обчислюютьсяЗапишіть позицію і пропустіть їїПеревірте, чи область в оригінальному файлі візуально об'єднана
iter_rows на півдорозі StopIterationПошкодження потоку XML або розділення ZIPАномалії захоплення та зсуви записівВідкрийте їх вручну в Excel або WPS для підтвердження відповідної області
Пам'ять росте повільноНе закрито або кеш не звільненоПримусовий моніторинг після gc.collect().Перевірте, чи мають глобальні змінні посилання на комірки
Назва поля заголовка містить невидимі символиПроблеми кодування експортної системиОчищення стрічки()Підтверджуйте відносини з картографуванням полів із бізнес-партнерами

Особлива примітка: reset_dimensions() не є панацеєю. Якщо сам файл не записує жодної інформації про розмірність, цей метод може розширити область роботи до межі робочого аркуша (1048576 рядків), що призведе до недійсних обходів або навіть тайм-аутів. На цьому етапі слід вручну встановити розумну верхню межу разом із max_row або проактивно завершити зв'язок при зустрічі з N порожніх рядків поспіль. Ці судження не можна приймати лише за допомогою коду; для їх підтримки потрібні знання домену.

🎯 Який метод тобі підходить?

Якщо потрібно одночасно обробляти сотні тисяч рядків таблиці,

Використовуйте read_only=True streaming reading, щоб уникнути стрибків пам'яті в режимі за замовчуванням.

Якщо ваш скрипт обробляє кілька файлів у циклі,

Явно викликайте wb.close() у блоці finally, щоб запобігти витоку ручки.

Якщо кількість прочитаних рядків значно менша за вихідні дані,

Спочатку перевірте, чи записано dimensions неправильно, потім перечитайте reset_dimensions() і порівняйте з експортним журналом вихідної системи.

Якщо вам потрібно читати стилі чи коментарі

Режим лише для читання не підтримує ці властивості; режим за замовчуванням слід використовувати або обробляти окремо в інших робочих процесах.

Точка входу для запуску зразків пам'яті

Наступний код виконується після наведеної функції, використовує лише синтетичні дані і не читає клієнтські файли.

from io import BytesIO
from openpyxl import Workbook
source = Workbook()
source.active.append(["id", "value"])
source.active.append(["A", 1])
source.active.append(["B", 2])
out = BytesIO()
source.save(out)
out.seek(0)
assert safe_read_large_excel(out, expected_min_rows=3) == 3

Використовуйте цей чек-лист для перекладу документів

Спочатку визначте, який зміст є текстом, а який — формулою та бізнес-кодом, потім перекладайте таблицю. Перевірка після перекладу не лише перевіряє, чи стала китайська цільова мова, а й перевіряє, чи були змінені формули, ідентифікатори та відношення цитувань.

OmniDoc (Запис продукту) надає багатоформатні портали перекладу документів, а її офіційний вебсайт пропонує OCR, глосарії та двомовні довідкові функції. Для команд, які хочуть починати безпосередньо з файлів, це шлях, який варто оцінювати за допомогою реальних зразків. Будь ласка, скористайтеся анонімізованим файлом, який ви дозволили для завантаження, і перевірте результати за допомогою чек-листа в цій статті. Ця стаття не стверджує, що OmniDoc використовує відкриті бібліотеки або внутрішні алгоритми, згадані в статті, а також не замінює тестування продуктивності продукту прикладами.

❓ Поширені запитання (FAQ)

1. Чому він закінчується на півдорозі читання і все одно не отримує помилки?

Тому що режим лише для читання довіряє заявленому файлу dimensions. Якщо система генерації записує ці метадані неправильно, ітератор завершує роботу раніше і не створює жодних винятків.

2. Чи можна обробляти всі великі файли за допомогою reset_dimensions()?

Ні. Якщо сам файл не містить інформації про розмірність, цей метод може розширити область видимості до 1048576 рядків, що спричиняє тайм-аути, і вимагає комбінації стратегій завершення max_row або послідовних стратегій завершення порожніх рядків.

3. Чому ви не можете читати стилі або змінювати клітинки в режимі лише для читання?

Режим лише для читання повертає ReadOnlyCell, який не підтримує доступ до стилю чи коментарів, а також не дозволяє змінювати значення. Це потрібно для підтримки використання пам'яті майже постійним.

4. Що слід перевірити після перекладу форми?

Окрім мовної коректності, також перевірте, чи були змінені формули, ідентифікатори та посилання.

📝 Резюме

Ключ до читання великих таблиць полягає у читанні потоків, перевірці розмірів і своєчасному випуску ресурсів. Код — це лише відправна точка; чи є дані повними, все одно залежить від порівняння та ручної перевірки.

Досвід зараз: завантажте документ, щоб почати переклад, зберігаючи оригінальне форматування

Оновлено 2026-11-15