Предполагая, что вы разместили буквальный формат файла, самое простое, что нужно сделать - это прочитать куски по 4 строки за раз и переключиться на первую строку. 1
Мы можем использовать рецепт grouper
из itertools
документов , который может разбить все на группы любого фиксированного размера.Но я покажу вам, как это сделать без рецепта, потому что стоит понять, как он работает:
with open('dataset.txt', 'r') as f:
# Create a list with 4 references to the same iterator.
iters = [iter(f)] * 4
# Zip into an iterator that grabs one value from each reference.
chunks = zip(*iters)
# Now each chunk is a tuple of four successive values.
for chunk in chunks:
Теперь, как мы включаем группы?Самое простое, что можно сделать здесь, это создать словарь, отображающий метки для выходных файлов:
outfiles = {'Handle': handles, 'OrgID': orgs, 'NetHandle': nets}
… затем просто извлечь метку из каждого чанка и найти выходной файл:
firstline = chunk[0]
label = firstline.split(':')[0]
outfile = outfiles[label]
Вы могли бы хотеть некоторую обработку ошибок здесь.Но если вы уверены, что в файле нет фрагментов, которые не соответствуют точно одному из этих трех форматов, этого, вероятно, достаточно. 2
это вместе:
with open('dataset.txt', 'r') as f, open('handles.txt', 'w') as handles, \
open('orgs.txt', 'w') as orgs, open('nets.txt', 'w') as nets:
outfiles = {'Handle': handles, 'OrgID': orgs, 'NetHandle': nets}
for chunk in zip(*([iter(f)]*4)):
label = chunk[0].split(':')[0]
outfiles[label].writelines(chunk)
Или, если вы используете рецепт grouper
(который вы должны):
with open('dataset.txt', 'r') as f, open('handles.txt', 'w') as handles, \
open('orgs.txt', 'w') as orgs, open('nets.txt', 'w') as nets:
outfiles = {'Handle': handles, 'OrgID': orgs, 'NetHandle': nets}
for chunk in grouper(f, 4):
label = chunk[0].split(':')[0]
outfiles[label].writelines(chunk)
Если файл на самом деле не заканчивается вНовая строка, последний кусок потерпит неудачу.Но это легко исправить, указав ''
как fillvalue
:
for chunk in grouper(f, 4, ''):
1.Вы можете сделать вещи чуть более эффективными - хотя и не такими простыми - если предположите, что сначала идут все чанки Handle, затем все чанки OrgID, а затем все чанки NetHandle.Но когда я спросил, было ли это правдой, вы просто ответили: «Они все кусками», и это ничего не решает.Итак, я напишу это, чтобы учесть вероятность того, что они смешаны.
2.Если вы ошибаетесь, и один из кусков начинается с 'Spam:'
, вы получите KeyError: 'Spam'
.Или, если один из чанков не имеет длины в 4 строки, так что в итоге вы выйдете из синхронизации и прочитаете Street:
в качестве первой строки, вы получите KeyError: 'Street'
.Таким образом, любой неожиданный ввод должен быть легко отлажен.