Как стать автором
Обновить

Комментарии 30

  1. Собственно, можно обойтись и без костыля в виде (к тому же не бесплатного) vedit-а, который особо не автоматизируется, а требует нескольких десятков кликов вручную. Первая же ссылка в гугле по запросу python xml splitter выдает вот это. Если почитать код, понятно, что считывается в память и парсится оно чанками, а не все сразу. (Понятно, что наверняка есть еще куча других "резчиков", которые делают то же самое.)
  2. Преобразование float64 во float32 и особенно int64 в uint8 может быть опасно по всем понятным причинам (потеря точности в первом случае и переполнение во втором). Нужно учитывать специфику данных.
1. Очень помогло. Доработал код по вашей ссылке под python 3 и русские символы, которые он не читал — код.
Синтаксис сохранен:
python xml-cut-chunk.py -o ./output/ -M 500000 big.xml

2.Да, это вынужденная мера, чтобы освободить память. По значениям, которые встречаются в столбцах, это допустимо.

ps. vedit -30 дней бесплатно.

Спасибо! Если не сложно, выложите на Github, пожалуйста (как-то не очень комильфо хранить исходники на Яндекс.Диске, плюс вдруг кто-нибудь еще захочет доработать).

Не пользуюсь гитхабом, несмотря на всю его привлекательность.
чтобы обработать xml большого размера, совсем необязательно загружать его в память или пользоваться сторонними приложениями. мне тоже довелось работать с ФИАС, и я читал данные из файла XmlReader'ом (.net).
Примерно так:
 var reader = XmlReader.Create(xml);
 while (!reader.EOF)
 {
      reader.Read();
      ...
 }

В Python нет чего-то похожего?
Когда читаешь подобный заголовок, надеешься, что будет что-то типа lxml.de/parsing.html#iterparse-and-iterwalk а тут XML2CSV и нет ответа как работать с большими XML при маленьком количестве оперативки. Это что, сезон курсовых на хабре опять? до нового года еще далеко.
Извините за снобизм
Так файл не парсится целиком. Поэтому путь через разбиение и конвертацию.
Кроме того, после нее размеры файлов уменьшаются в разы.
Ну так вам и говорят, что это ручное разбиение и конвертация — это костыль, а не нормальное взрослое решение :) Вот для файла в всего 3 Гб работает, а что вы будете делать с файлом в 30 Гб? Файл и не надо парсить целиком, вон же ссылка выше про парсинг по частям (если структура позволяет).
Тогда тем более не ясна ваша ссылка на итераторы.
Для этого много лет назад придумали SAX-парсеры.
Можно читать XML не превращая его в объектную модель в памяти, а держать лишь маленький контекст, соответствующий максимум одной записи.
SAX-парсер устроен так, что в нём описывается код реакции на каждый элемент XML. Причем отдельно описывается реакция на открытие и закрытие каждого тега. Так на закрытие тега поля можно сохранять значение поля в буфферный словарик под соответствующим ключем, а на закрытие тега записи сохранять накопившийся словарик в CSV-файл в потоковом режиме дописывая в него строчку.
Так и террабайтные xml можно без мороки обрабатывать, лишь бы одна максимальная его запись в память помещалась. Думаю на гитхабе готовых SAX XML to CSV конвертеров валом. Ну или стоит сделать, если нет (хотя я сильно удивлюсь). Думаю код поместится на полтора экрана со всеми обработками ошибок и CLI.
Ну, ради объективности, это ФИАС такой простой, что у него одна запись. У меня были случаи, когда нужно было парсить 8 гигабайт, при этом данные размазаны по иерархии XML. Так что я вынужден был держать верхние уровни в памяти тоже, да и конкретно SAX при этом большого удовольствия не доставляет.

P.S. Отдельный вопрос — почему бы не прочитать ФИАС в формате .dbf, где такой проблемы вообще не существует как класса.

На счёт дбф я даже не стал упоминать ввиду очевидности. А где 8 гигов, там и 28. Никакой памяти не напасешься, так что конвертить тем же саксом во что-то удобоваримое типа набора быстрых key-value коллекций на диске или реляционной бд или той же монги и работать уже с этим. Да, метод "сакс", но как иначе построить масштабируемое решение?

Очевидно что принципиально больше никак. И против решения ничего не имею, это было лишь небольшое уточнение. Впрочем, как вариант могу предложить что-то вроде этого:

jawher.wordpress.com/2011/02/28/introducing-immanix-java-library-process-xml-using-parser-combinators

Я пользовался, в том числе для разбора 8 гиговых xml. По сравнению с голым SAX — чуть удобнее, примерно при тех же ресурсах.

А упоминание про .dbf… ну не знаю, я как-то запросил у смежной команды периодически импортировать к нам OpenStreetMap. При этом явно написал — берите pbf. Потому что содержимое идентично, а размеры в разы меньше. И что бы вы думали — в итоге реализовали импорт из xml. Считайте, что это была агитация за то, чтобы рассмотреть все варианты :)
Аналогично, парсил ФИАС используя простую конструкцию
        using (var xmlReader = new XmlTextReader(file))
        {
          while (xmlReader.Read())
          {
            if (xmlReader.Name != "Object")
              continue;

            var address = XElement.Load(xmlReader.ReadSubtree());
            ...
          }
        }
Почти не требует памяти (Мне хватало 128мб, с учетом того что в памяти хранились все нужные объекты, но я только до городов сверху вниз парсил), работает довольно шустро.
НЛО прилетело и опубликовало эту надпись здесь
Ага…
героически игнорируем гениальный по экономичности подход SAX парсеров
сохраняем руками в четыре файла (open, seek, read/write уж на крайний случай)
используем замечательный инструмент (спасибо за явную конверсию типов, раньше не обращал внимание),
но для чего? Переименовать столбцы и сохранить в итоговый файл?
Изложите ваш подход? Опыт бесценен.
habr.com/ru/post/171447
уже есть вполне готовый пример. Или интересует именно ФИАС, питоном и пачкой зараз?
Но смысл? В чем сверхзадача?
Получить данные — это один промежуточный процесс, потом с ними надо что-то сделать полезное.
Сверхзадача — выяснить как чувствует себя pandas при малых объемах памяти и большим датасетом, если ли предел модуля. Какова скорость работы на сверхбольших данных.

Странно, что все смотрят только в сторону конвертации xml-csv.
Учитывая, что внутри прячется numpy, то ответ довольно предсказуемый.
Немного лучше, чем нативный код на питоне.
www.draketo.de/english/python-memory-numpy-list-array

В любом случае Pandas пока что хранит данные в оперативной памяти, так что всё плохо и будет потихоньку выпадать в своп при превышении
НЛО прилетело и опубликовало эту надпись здесь
Делал похожую задачу, тоже связанную с ФНС (данные о среднесписочном составе — представляют собой огромное кол-во XML — файлов. Требовалось привести их к виду, привычному для юристов — электронной таблице Excel, т.е. много мелких XML файлов объединить в одну или несколько таблиц Excel) с помощью XSLT -преобразования. Реализовал с помощью программы xsltproc пакета libxslt (в archlinux, в других дистрах может по другому). Самым сложным было сочинить XSL-фильтр, через который прогонялся XML-файл, т.к. довольно редко приходится работать с данными в XML, но хотелось сделать красиво.
Много мелких файлов и один большой файл — это две совершенно непохожие задачи. Особенно в свете xslt, которому нужна вся модель документа в памяти.
Наверное, всё-таки похожие, поскольку я не думаю что XSLT-фильтр сначала целиком прочитывает весь файл в память, а потом разбирает его. Я склонен к тому что он делает это порциями, по мере чтения файла. Но на 100% пока не уверен, т.к. сам лично не проверял.
>Наверное, всё-таки похожие, поскольку я не думаю что XSLT-фильтр сначала целиком прочитывает весь файл в память, а потом разбирает его.
Ага, ага. Только если у вас XSLT 3.0, в чем я сильно сомневаюсь.

Специальная утилита для склеивания CSV-файлов. Серьёзно?

Если вы это в сети нашли: copy *.csv big.csv, то там названия столбцов не задаются при склейке.
Вы можете сделать первый файл с названиями столбцов
copy header.csv + 1.csv + 2.csv +… big.csv

Это вы про a,b,c т.д.? Да, это большая потеря.
А имя файла в tree = ET.parse("add-30-40.xml",parser=parser) вы вручную каждый раз подставляли? Нельзя было просто циклом пройтись сразу по всем XML-файлам и записать разом в один CSV файл?
Кстати, заголовок в CSV вообще не обязателен (в т.ч. для pandas).

Нельзя было просто циклом пройтись сразу по всем XML-файлам и записать разом в один CSV файл?

С адресным реестром (база из статьи) это возможно. А вот с «домами» — база из архива на 29 Гб уже нет, так как база битая — некоторые теги не закрыты, поэтому парсер вылетает.
*Из 119 чанок по 220 Мб, только половина парсится без проблем.
Кроме того, не ясна структура, а большой файл после создания не открыть для уточнения.
Кстати, заголовок в CSV вообще не обязателен (в т.ч. для pandas).

Все верно. Эти названия необходимы для ориентации в датасете.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории