Задать вопрос
@AsphaltHero_0
Road to DevOps

Как быстро распарсить много json файлов на python?

Стоит задача распарсить 8000 Json файлов, объем всего этого добра ~ 8 гигов. Нужно вытащить нужную информацию и записать в базу. На файл уходит по 2 секунды. То есть на все файлы ~5 часов. Ищу решение как сделать быстрее, учитывая, что i\o biund операция.
Прошу всех неравнодушных и не душных подсказать куда копать!

Вот часть кода
for filename in os.listdir(download_dir):
        if filename.endswith('.json'):
            with open(os.path.join(download_dir, filename), 'r', encoding='utf-8') as j_f:
                try:
                    data = json.load(j_f)
                    companies_to_create = []
                    for d in data:
                        if isinstance(d, dict):
                            inn = d.get('inn', '')
                            kpp = d.get('kpp', '')
                            name = d.get('name', '')
                            address_ul = d.get('data', {}).get('СвРегОрг', {}).get('АдрРО', '')
                            sv_okved = d.get('data', {}).get('СвОКВЭД', {})
                            if sv_okved:
                                sv_okved_dop = sv_okved.get('СвОКВЭДДоп', [])
                                for sv in sv_okved_dop:
                                    if isinstance(sv, dict) and sv.get('КодОКВЭД', '').startswith('96'):
                                        okved = sv.get('КодОКВЭД', '')
                                        if not "Хабаровск" in address_ul:
                                            existing_company = Company.objects.filter(inn=inn).first()
                                            if not existing_company:
                                                company = Company(
                                                    name=name,
                                                    okved=okved,
                                                    inn=inn,
                                                    kpp=kpp,
                                                    address_ul=address_ul,
                                                )
                                                companies_to_create.append(company)
                    Company.objects.bulk_create(companies_to_create)
  • Вопрос задан
  • 338 просмотров
Подписаться 2 Простой 3 комментария
Решения вопроса 1
Maksim_64
@Maksim_64
Data Analyst
Ну во первых, pandas read_json и json_normalize (для вложенных json). Затем этот фрейм или подсет фрейма отправляешь в базу, методом to_sql если все делаешь правильно с точки зрения pandas (весь код будет без единого цикла) то это ускорит очень серьезно. Еще больше можно ускорить библиотекой polars она имеет схожий синтакс с pandas у ней куда меньший функционал по манипуляции данных, но она фокусируется на скорости в том числе и чтения файлов.

Думаю скорости pandas будет достаточно, если нет то polars. Начать лучше с pandas документация очень хорошая, да и кода всего ничего будет.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
mayton2019
@mayton2019
Bigdata Engineer
А почему ты решил что парсинг это узкое место? Ты пишешь информацию в базу. Тоесть у тебя конвейер операций.
И я думаю что до того как начинать оптимизацию, надо собрать логи по таймингам. Сколько милисекунд занимет
чистый парсинг и сколько запись в БД.

Попробуй еще простой параллелизм. Разбей эти 8000 файлов на 2 фолдера по 4000.
И запусти 2 python-процесса. Будет допустим не 5 часов а 3 часа. Уже лучше.
Продолжнай дробить пока удельная скорость обработки не деградирует.
Ответ написан
@rPman
Если узкое место - разбор огромного json, то тебе нужен потоковый парсер, их огромное количество, гугл для питона выдает к пример ijson.

Если этого будет мало, попробуй переписать это место на c/c++, там еще быстрее парсеры, например simdjson обещает гигабайты в секунду (и это реально так)

Эти парсеры пробегают линейно по токенам, а ты в процессе принимаешь решение нужно ли пропустить данный токен (или целый подраздел) или обрабатывать далее, благодаря такому подходу в оперативной памяти не сохраняется ничего из входного json а потоковый подход позволяет даже распаралелить обработку (в отдельном потоке/процессе ты анализируешь json а в другом пишешь в базу данных)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы