привет!
прошу подсказать как можно улучшить следующий код для обработки здоровенного 30GB текстового файла со строками.
требуется:
a) удалить в файле символ "|"
б) удалить все до первой открытой скобки "<"
в) удалить в конце файла всё что начинается на символ "-"
г) удалить в кажд строке пробелы в начале и в конце
д) удалить пустые строки
е) присоединить в конец кажд строки символ '."
как я это пока себе представляю:
def process(lines):
dataStr = "".join(lines)
# remove | globally
p = re.compile(r'\|')
dataStr = p.sub("", dataStr)
# fix header
p = re.compile(r'^[^<]*')
dataStr = p.sub("", dataStr)
#fix footer
p = re.compile('-*$')
dataStr = p.sub("", dataStr)
# delete BOTH leading and trailing whitespace from each line
#TODO: do better
data =dataStr.split('\n')
#remove empty lines
data = list(filter(lambda x: len(x) > 0, data))
#append ending . to each line
data = [l.strip() + '.'for l in data]
return data
if __name__ == "__main__":
if len(sys.argv) != 2:
print "usage: %s %s" % (sys.argv[0], "dump.txt")
exit(-1)
else:
fname = sys.argv[1]
with open(fname, "r+") as file:
data = list()
i = 0
while True:
if i >= 100000:
result = process(data)
#TODO: append result to output file
i = 0
data = list()
else:
line = file.readline()
if not line:
if data:
result = process(data)
#TODO: append result to output file
break
data.append(line)
i += 1
т.е. читаю в список по сто тыщ строк, и обрабатываю их, записываю в выходной файл. и так пока не кончатся данные все из исходного файла.
смущает явные излишние "кувыркания" данных в ф-ции "process" и назад: list_of_strings <--> string. как сделать лаконичней, а самое главное, быстрее по времени исполнения? спасибо!
Здравствуйте, sinmaster, Вы писали: S>прошу подсказать как можно улучшить следующий код для обработки здоровенного 30GB текстового файла со строками.
Внезапно, гугл занимается грепом на кластере и использует MapReduce (http://labs.google.com/papers/mapreduce.html). Может, стоит заюзать какой-нибудь фреймворк для MR?
S>привет! S>прошу подсказать как можно улучшить следующий код для обработки здоровенного 30GB текстового файла со строками. S>требуется: S>a) удалить в файле символ "|" S>б) удалить все до первой открытой скобки "<" S>в) удалить в конце файла всё что начинается на символ "-" S>г) удалить в кажд строке пробелы в начале и в конце S>д) удалить пустые строки S>е) присоединить в конец кажд строки символ '."
S>т.е. читаю в список по сто тыщ строк, и обрабатываю их, записываю в выходной файл. и так пока не кончатся данные все из исходного файла. S>смущает явные излишние "кувыркания" данных в ф-ции "process" и назад: list_of_strings <--> string. как сделать лаконичней, а самое главное, быстрее по времени исполнения? спасибо!
Во-первых, быстрее и питон.. мухи отдельно, котлеты отдельно.
Чтобы сделать это быстрее, нужно написать примерно такой пайп на шеллскрипте:
cat input | sed \
# a) удалить в файле символ "|"
-e 's/|//' \
-e 's/.*\<\(.*\)/\\1/' \ # здесь может быть синтаксически неправильно, но смысл думаю понятен
... т.д. остальные правила
> output
Чтобы сделать это на питоне... В двух словах: нужно убрать магическое число сто тыщ (с буферизацией OS справится лучше, чем вы) и не использовать list <--> string, а обрабатывать каждую строку отдельно.
def process_file(f):
for s in f:
# пропускаем пустые строки
if s:
yield process_line(s)
def process_line(s):
# Внимание: в конце этой строки есть символ перевода строки.
# a) удалить в файле символ "|"
s = s.replace('|', '')
... остальные правила
# г) удалить в кажд строке пробелы в начале и в конце
s = s.strip(' ') # уберите ' ' чтобы удалить любые пробельные символы (\t\v\r\n...), но тогда добавить символ перевода строки в конец надо будет самому
# е) присоединить в конец кажд строки символ '."
s = s + '.'
return s
fin = open("/path", 'r')
fout = open("/other", 'w')
for s in process_file(fin):
fout.write(s)
fin.close()
fout.close()
S>>прошу подсказать как можно улучшить следующий код для обработки здоровенного 30GB текстового файла со строками. MC>Внезапно, гугл занимается грепом на кластере и использует MapReduce (http://labs.google.com/papers/mapreduce.html). Может, стоит заюзать какой-нибудь фреймворк для MR?
на sed у меня уже есть накатанный рабочий вариант, но т.к. я изучаю счас Питон, захотел и его попробовать. просто для самообучения, благо задача подвернулась хорошая. спасибо за пояснения, вдумываюсь в питоновский пример ваш.
S>на sed у меня уже есть накатанный рабочий вариант, но т.к. я изучаю счас Питон, захотел и его попробовать. просто для самообучения, благо задача подвернулась хорошая. спасибо за пояснения, вдумываюсь в питоновский пример ваш.
Если нужно на питоне и быстро, то есть смысл посмотреть в сторону Cython.
А если для самообучения то вроде быстро не надо же, хотя тут конечно, каждый по-своему считает.
Здравствуйте, Temoto, Вы писали: T>Казалось бы, причём тут гугл.
Про кого сам читал — про того и написал. Ну и хороший пример конторы, у которой обрабатываются большие объемы данных.
Здравствуйте, Temoto, Вы писали:
S>>если парсить построчно, то неслишком красиво получится реализовать пункт бэ)
T>Удалить всё до первой открытой скобки? А нужно удалить в т.ч. все предыдущие строки?
T>lalala T>zar<h1>
T>И нужно lalala тоже удалить? Тут два решения — простое, если '<' точно встречается в файле и сложное, если неизвестно — будет скобка или нет.
нужно удалить "lalala\nzar", т.е. чтобы в итоге осталось только "<h1>foo\nbarbar\n\n\n\bazfred...etc".
в моем случае "<" точно встречается в файле, в строчке где-то 5-10 от начала файла.
если не прибегать к регекспам (ведь мы обрабатываем построчно), то придется вводить if и проверять булев флажок, чтобы блок в if выполнился 1 раз.
S>>>если парсить построчно, то неслишком красиво получится реализовать пункт бэ)
T>>Удалить всё до первой открытой скобки? А нужно удалить в т.ч. все предыдущие строки?
T>>lalala T>>zar<h1>
T>>И нужно lalala тоже удалить? Тут два решения — простое, если '<' точно встречается в файле и сложное, если неизвестно — будет скобка или нет.
S>нужно удалить "lalala\nzar", т.е. чтобы в итоге осталось только "<h1>foo\nbarbar\n\n\n\bazfred...etc". S>в моем случае "<" точно встречается в файле, в строчке где-то 5-10 от начала файла. S>если не прибегать к регекспам (ведь мы обрабатываем построчно), то придется вводить if и проверять булев флажок, чтобы блок в if выполнился 1 раз.
Не надо флажки. Флажки делает умный компилятор, когда компилирует конечный автомат. Питонячий компилятор подобные конечные автоматы оптимизировать не умеет (и никогда не будет уметь), а человек — плохой умный компилятор.
def process_file(f):
# пропускаем всё до символа '<'
# Внимание! Если в файле не было символа '<', то на выходе будет пустота.for s in f:
if'<'in s:
_, after = s.split('<', 1)
yield process_line('<' + after)
break
for s in f:
# пропускаем пустые строкиif s:
yield process_line(s)