Comments 30
- Собственно, можно обойтись и без костыля в виде (к тому же не бесплатного) vedit-а, который особо не автоматизируется, а требует нескольких десятков кликов вручную. Первая же ссылка в гугле по запросу
python xml splitter
выдает вот это. Если почитать код, понятно, что считывается в память и парсится оно чанками, а не все сразу. (Понятно, что наверняка есть еще куча других "резчиков", которые делают то же самое.) - Преобразование float64 во float32 и особенно int64 в uint8 может быть опасно по всем понятным причинам (потеря точности в первом случае и переполнение во втором). Нужно учитывать специфику данных.
1. Очень помогло. Доработал код по вашей ссылке под python 3 и русские символы, которые он не читал — код.
Синтаксис сохранен:
2.Да, это вынужденная мера, чтобы освободить память. По значениям, которые встречаются в столбцах, это допустимо.
ps. vedit -30 дней бесплатно.
Синтаксис сохранен:
python xml-cut-chunk.py -o ./output/ -M 500000 big.xml
2.Да, это вынужденная мера, чтобы освободить память. По значениям, которые встречаются в столбцах, это допустимо.
ps. vedit -30 дней бесплатно.
чтобы обработать xml большого размера, совсем необязательно загружать его в память или пользоваться сторонними приложениями. мне тоже довелось работать с ФИАС, и я читал данные из файла XmlReader'ом (.net).
Примерно так:
В Python нет чего-то похожего?
Примерно так:
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.
Можно читать XML не превращая его в объектную модель в памяти, а держать лишь маленький контекст, соответствующий максимум одной записи.
SAX-парсер устроен так, что в нём описывается код реакции на каждый элемент XML. Причем отдельно описывается реакция на открытие и закрытие каждого тега. Так на закрытие тега поля можно сохранять значение поля в буфферный словарик под соответствующим ключем, а на закрытие тега записи сохранять накопившийся словарик в CSV-файл в потоковом режиме дописывая в него строчку.
Так и террабайтные xml можно без мороки обрабатывать, лишь бы одна максимальная его запись в память помещалась. Думаю на гитхабе готовых SAX XML to CSV конвертеров валом. Ну или стоит сделать, если нет (хотя я сильно удивлюсь). Думаю код поместится на полтора экрана со всеми обработками ошибок и CLI.
Ну, ради объективности, это ФИАС такой простой, что у него одна запись. У меня были случаи, когда нужно было парсить 8 гигабайт, при этом данные размазаны по иерархии XML. Так что я вынужден был держать верхние уровни в памяти тоже, да и конкретно SAX при этом большого удовольствия не доставляет.
P.S. Отдельный вопрос — почему бы не прочитать ФИАС в формате .dbf, где такой проблемы вообще не существует как класса.
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. Считайте, что это была агитация за то, чтобы рассмотреть все варианты :)
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 уж на крайний случай)
используем замечательный инструмент (спасибо за явную конверсию типов, раньше не обращал внимание),
но для чего? Переименовать столбцы и сохранить в итоговый файл?
героически игнорируем гениальный по экономичности подход SAX парсеров
сохраняем руками в четыре файла (open, seek, read/write уж на крайний случай)
используем замечательный инструмент (спасибо за явную конверсию типов, раньше не обращал внимание),
но для чего? Переименовать столбцы и сохранить в итоговый файл?
Изложите ваш подход? Опыт бесценен.
habr.com/ru/post/171447
уже есть вполне готовый пример. Или интересует именно ФИАС, питоном и пачкой зараз?
Но смысл? В чем сверхзадача?
Получить данные — это один промежуточный процесс, потом с ними надо что-то сделать полезное.
уже есть вполне готовый пример. Или интересует именно ФИАС, питоном и пачкой зараз?
Но смысл? В чем сверхзадача?
Получить данные — это один промежуточный процесс, потом с ними надо что-то сделать полезное.
Сверхзадача — выяснить как чувствует себя pandas при малых объемах памяти и большим датасетом, если ли предел модуля. Какова скорость работы на сверхбольших данных.
Странно, что все смотрят только в сторону конвертации xml-csv.
Странно, что все смотрят только в сторону конвертации xml-csv.
Учитывая, что внутри прячется numpy, то ответ довольно предсказуемый.
Немного лучше, чем нативный код на питоне.
www.draketo.de/english/python-memory-numpy-list-array
В любом случае Pandas пока что хранит данные в оперативной памяти, так что всё плохо и будет потихоньку выпадать в своп при превышении
Немного лучше, чем нативный код на питоне.
www.draketo.de/english/python-memory-numpy-list-array
В любом случае Pandas пока что хранит данные в оперативной памяти, так что всё плохо и будет потихоньку выпадать в своп при превышении
Делал похожую задачу, тоже связанную с ФНС (данные о среднесписочном составе — представляют собой огромное кол-во XML — файлов. Требовалось привести их к виду, привычному для юристов — электронной таблице Excel, т.е. много мелких XML файлов объединить в одну или несколько таблиц Excel) с помощью XSLT -преобразования. Реализовал с помощью программы xsltproc пакета libxslt (в archlinux, в других дистрах может по другому). Самым сложным было сочинить XSL-фильтр, через который прогонялся XML-файл, т.к. довольно редко приходится работать с данными в XML, но хотелось сделать красиво.
Много мелких файлов и один большой файл — это две совершенно непохожие задачи. Особенно в свете xslt, которому нужна вся модель документа в памяти.
Наверное, всё-таки похожие, поскольку я не думаю что XSLT-фильтр сначала целиком прочитывает весь файл в память, а потом разбирает его. Я склонен к тому что он делает это порциями, по мере чтения файла. Но на 100% пока не уверен, т.к. сам лично не проверял.
Специальная утилита для склеивания CSV-файлов. Серьёзно?
Если вы это в сети нашли:
copy *.csv big.csv
, то там названия столбцов не задаются при склейке.Вы можете сделать первый файл с названиями столбцов
copy header.csv + 1.csv + 2.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).
Все верно. Эти названия необходимы для ориентации в датасете.
Sign up to leave a comment.
Как обработать большие датасеты в pandas. Работаем с базой ФИАС, используя python и 8Гб памяти