Python — как читать большие XML файлы при ограничении оперативной памяти

Рассмотрим на конкретном примере, как обработать большой каталог книг в формате XML размером 3 Гб.

Задача: скачать каталог по ссылке https://www.litres.ru/static/ds/detailed_data.xml.gz и узнать количество книг в каталоге.

Пример структуры полного каталога книг Литрес в формате XML
Пример структуры полного каталога книг Литрес в формате XML

Предварительно я скачал архив с xml и изучил, в каком теге лежит информация о книге. Это тег “art”. Теперь нам нужно написать скрипт, который найдёт все узлы с тегом “art” и посчитать их количество.

Для разбора xml используем встроенную библиотеку xml.etree.ElementTree.

import xml.etree.ElementTree as ET

books = 0
for (event, node) in ET.iterparse('detailed_data.xml', events=['end']):
    if node.tag == "art" and event == "end":
        books += 1
        node.clear()

print(books)

Всего получилось 1 051 440 книг.

Как работает модуль iterparse() — постепенно проходит по xml-дереву элементов и возвращает два значения: событие event и узел с данными node.

Есть шесть событий events, но мы рассмотрим только два:

  • start – найден открывающий тег <node>
  • end – найден закрывающий тег </node>

В данной задаче нас интересует событие end, поэтому мы его и передали в параметры iterparse events=['end']. То есть, если мы находим закрывающий тег “art”, то увеличиваем значение books на единицу. После этого указываем команду node.clear(), чтобы освободить оперативную память от этого узла и работаем дальше.

Собственно весь секрет обработки больших xml файлов заключается в том, чтобы загружать в оперативную память только небольшой кусочек файла и после обработки – удалять его из памяти и переходить к следующему.