Я получил большой текстовый файл (10 ГБ, .xml, содержит более чем 1 миллион тегов как это: <record>
текст</record>
) который я splitted в части для использования его. Но смочь автоматизировать мой рабочий процесс, необходимо, чтобы каждый расстается концы с определенным тегом: </record>
. И также необходимо, чтобы каждая часть имела, по крайней мере, размер приблизительно 40 МБ.
Сценарий ниже частей (большой) файл в части. Я не использовал split
команда, так как содержание Вашего файла должно быть "округлено" записями. Размер частей можно установить в главном разделе сценария.
Трудности
Поскольку сценарий должен смочь иметь дело с огромными файлами, любой Python read()
или readlines()
не может использоваться; сценарий попытался бы загрузить целый файл сразу в память, которая будет, конечно, дросселировать Вашу систему. В то же время подразделения должны быть сделаны, "округлив" разделы целой записью. Сценарий должен поэтому так или иначе смочь определить или "считать" содержание файла.
То, что, кажется, единственная опция, должно использовать:
with open(file) as src:
for line in src:
который читает файл линию за линией.
Подход
В сценарии я выбрал двухступенчатый подход:
Процедура для добавления строк к отдельным частям (файлы) один за другим кажется неэффективной, но от всего я попробовал ее, оказался самым эффективным, самым быстрым и наименьшим количеством опции потребления.
Как я протестировал
Я создал xml
файл немногим более, чем 10 ГБ, заполненных записями как Ваш пример. Я установил размер частей к 45mb
. В моей not-so-recent системе (Pentium Двухъядерный ЦП E6700 3.20 ГГц × 2), анализ сценария произвел следующее:
analyzing file...
checking file size...
file size: 10767 mb
calculating number of slices...
239 slices of 45 mb
checking number of lines...
number of lines: 246236399
checking number of records...
number of records: 22386000
calculating number records per section ...
records per section: 93665
Затем это начало создавать части 45 МБ, беря appr. 25-27 секунд на часть для создания.
creating slice 1
creating slice 2
creating slice 3
creating slice 4
creating slice 5
и так далее...
Процессор был занят для 45-50% во время процесса, с помощью ~850-880mb моей памяти (4 ГБ). Компьютер был довольно применим во время процесса.
Целая процедура заняла полтора часа. В более свежей системе должно потребоваться существенно меньше времени.
#!/usr/bin/env python3
import os
import time
#---
file = "/path/to/big/file.xml"
out_dir = "/path/to/save/slices"
size_ofslices = 45 # in mb
identifying_string = "</record>"
#---
line_number = -1
records = [0]
# analyzing file -------------------------------------------
print("analyzing file...\n")
# size in mb
print("checking file size...")
size = int(os.stat(file).st_size/1000000)
print("file size:", size, "mb")
# number of sections
print("calculating number of slices...")
sections = int(size/size_ofslices)
print(sections, "slices of", size_ofslices, "mb")
# misc. data
print("checking number of lines...")
with open(file) as src:
for line in src:
line_number = line_number+1
if identifying_string in line:
records.append(line_number)
# last index (number of lines -1)
ns_oflines = line_number
print("number of lines:", ns_oflines)
# number of records
print("checking number of records...")
ns_records = len(records)-1
print("number of records:", ns_records)
# records per section
print("calculating number records per section ...")
ns_recpersection = int(ns_records/sections)
print("records per section:", ns_recpersection)
# preparing data -------------------------------------------
rec_markers = [i for i in range(ns_records) if i% ns_recpersection == 0]+[ns_records] # dividing records (indexes of) in slices
line_markers = [records[i] for i in rec_markers] # dividing lines (indexes of) in slices
line_markers[-1] = ns_oflines; line_markers.pop(-2) # setting lias linesection until last line
# creating sections ----------------------------------------
sl = 1
line_number = 0
curr_marker = line_markers[sl]
outfile = out_dir+"/"+"slice_"+str(sl)+".txt"
def writeline(outfile, line):
with open(outfile, "a") as out:
out.write(line)
with open(file) as src:
print("creating slice", sl)
for line in src:
if line_number <= curr_marker:
writeline(outfile, line)
else:
sl = sl+1
curr_marker = line_markers[sl]
outfile = out_dir+"/"+"slice_"+str(sl)+".txt"
print("creating slice", sl)
writeline(outfile, line)
line_number = line_number+1
Скопируйте сценарий в пустой файл, установите путь в Ваш "большой файл", путь к каталогу для сохранения частей и размера частей. Сохраните его как slice.py
и выполненный это командой:
/path/to/slice.py