slurp/csv/loop файл для создания списка словарей
У меня есть большой файл (1,6 гигабайта) с миллионами строк, столбцы которых разделены:
[||]
Я пытался использовать модуль CSV, но он говорит, что я могу использовать только один символ в качестве разделителя. Итак, вот что я имею:
fileHandle = open('test.txt', 'r', encoding="UTF-16")
thelist = []
for line in fileHandle:
fields = line.split('[||]')
therow = {
'dea_reg_nbr':fields[0],
'bus_actvty_cd':fields[1],
'drug_schd':fields[3],
#50 more columns like this
}
thelist.append(therow)
fileHandle.close()
#now I have thelist which is what I want
И бум, теперь у меня есть список словарей, и это работает. Я хочу список, потому что я забочусь о порядке, и словарь, потому что вниз по течению это ожидается. Такое ощущение, что я должен воспользоваться чем-то более эффективным. Я не думаю, что это хорошо масштабируется с более чем миллионом строк и таким большим количеством данных. Итак, мой вопрос таков:
Что может быть более эффективным способом получения многосимвольного текстового файла с разделителями (в кодировке UTF-16) и создания списка словарей?
Любые мысли будут оценены!
1 ответ
Один из способов улучшить его масштабирование - использовать генератор вместо загрузки всех миллионов строк в память одновременно. Это может или не может быть возможно в зависимости от вашего варианта использования; это будет работать лучше всего, если вам нужно всего лишь сделать один проход для полного набора данных. Многократные проходы потребуют, чтобы вы либо сохранили все данные в памяти в той или иной форме, либо считывали их из файла несколько раз.
Во всяком случае, вот пример того, как вы могли бы использовать генератор для этой проблемы:
def file_records():
with open('test.txt', 'r', encoding='UTF-16') as fileHandle:
for line in fileHandle:
fields = line.split('[||]')
therow = {
'dea_reg_nbr':fields[0],
'bus_actvty_cd':fields[1],
'drug_schd':fields[3],
#50 more columns like this
}
yield therow
for record in file_records():
# do work on one record
Функция file_records
является функцией генератора из-за yield
ключевое слово. Когда эта функция вызывается, она возвращает итератор, который вы можете перебирать точно так же, как список. record
s будут возвращены в порядке, и каждый будет словарь.
Если вы не знакомы с генераторами, это хорошее место, чтобы начать читать о них.
То, что делает эту шкалу настолько хорошо, что у вас будет только один therow
в памяти одновременно. По сути, происходит то, что в начале каждой итерации цикла file_records
Функция читает следующую строку файла и возвращает вычисленную запись. Он будет ждать до тех пор, пока не понадобится следующая строка, прежде чем выполнять работу, и предыдущая запись не останется в памяти, если в ней нет необходимости (например, если на нее есть ссылка в любой структуре данных, которую вы строите # do work on one record
).
Обратите внимание, что я переместил open
позвонить with
заявление. Это обеспечит закрытие файла и освобождение всех связанных ресурсов после выполнения итерации или возникновения исключения. Это гораздо проще, чем пытаться поймать все эти случаи самостоятельно и звонить fileHandle.close()
,