лучший способ разбора больших файлов с помощью regex python

Мне нужно проанализировать большой файл журнала (2 ГБ), используя reg ex в python. В файле журнала регулярное выражение соответствует строке, которая меня интересует. Файл журнала также может содержать нежелательные данные.

Вот пример из файла:

"#DEBUG:: BFM [L4] 5.4401e+08ps MSG DIR:TX SCB_CB TYPE:DATA_REQ CPortID:'h8 SIZE:'d20 NumSeg:'h0001 Msg_Id:'h00000000"

Мое регулярное выражение ".DEBUG.*MSG."

Сначала я разделю его с помощью пробелов, затем шаблоны «поле: значение» будут вставлены в базу данных sqlite3; но для больших файлов анализ файла занимает от 10 до 15 минут.

Пожалуйста, предложите лучший способ сделать вышеуказанную задачу за минимальное время.


person user2109788    schedule 29.08.2013    source источник
comment
Не могли бы вы опубликовать пример строки журнала и шаблона, который вы ищете?   -  person Julien Chappuis    schedule 29.08.2013
comment
Формат будет аналогичен #DEBUG::BFM [L4] 5.4401e+08ps MSG DIR:TX SCB_CB TYPE:DATA_REQ CPortID:'h8 SIZE:'d20 NumSeg:'h0001 Msg_Id:'h00000000 и reg ex .DEBUG.*MSG .. Сначала я разделю его, используя пробелы, а затем в базу данных будут вставлены шаблоны поля: значения.   -  person user2109788    schedule 29.08.2013
comment
Возможно, вам лучше использовать программу, которая работает с потоком данных, например sed.   -  person Burhan Khalid    schedule 29.08.2013


Ответы (3)


Как уже говорили другие, профилируйте свой код, чтобы понять, почему он медленный. Модуль cProfile в сочетании с инструментом gprof2dot может создавать удобочитаемую информацию.

Не видя вашего медленного кода, я могу предположить несколько вещей, которые могут помочь:

Во-первых, вы, вероятно, можете обойтись без использования встроенных строковых методов вместо регулярного выражения - это может быть немного быстрее. Если вам нужно использовать регулярные выражения, стоит выполнить предварительную компиляцию вне основного цикла, используя re.compile

Во-вторых, не делать один запрос на вставку в строку, вместо этого делать вставки в пакетах, например, добавить проанализированную информацию в список, а затем, когда он достигнет определенного размера, выполнить один запрос INSERT с executemany.

Какой-то неполный код, как пример выше:

import fileinput

parsed_info = []
for linenum, line in enumerate(fileinput.input()):
    if not line.startswith("#DEBUG"):
        continue # Skip line

    msg = line.partition("MSG")[1] # Get everything after MSG
    words = msg.split() # Split on words
    info = {}
    for w in words:
        k, _, v = w.partition(":") # Split each word on first :
        info[k] = v

    parsed_info.append(info)

    if linenum % 10000 == 0: # Or maybe  if len(parsed_info) > 500:
        # Insert everything in parsed_info to database
        ...
        parsed_info = [] # Clear
person dbr    schedule 29.08.2013

Ответ Пола имеет смысл, вам нужно сначала понять, где вы «теряете» время. Самый простой способ, если у вас нет профилировщика, - это опубликовать временную метку в миллисекундах до и после каждого «шага» вашего алгоритма (открытие файла, чтение его построчно (и внутри, время, необходимое для разделения / регулярного выражения, чтобы распознать строки отладки), вставка его в БД и т. д.).

Без дальнейшего знания вашего кода возможны «ловушки», которые отнимают очень много времени: - открытие файла журнала несколько раз - открытие БД каждый раз, когда вам нужно вставить данные внутрь вместо того, чтобы открывать одно соединение, а затем писать по ходу дела.

person Julien Chappuis    schedule 29.08.2013
comment
К счастью, в python есть фантастический встроенный детальный профилировщик, поэтому альтернатива здесь не требуется. - person Slater Victoroff; 29.08.2013

«Лучший способ выполнить вышеуказанную задачу за минимальное время» — это сначала выяснить, куда уходит время. Посмотрите, как профилировать ваш скрипт Python, чтобы определить, какие части работают медленно. У вас может быть неэффективное регулярное выражение. Запись на sqlite может быть проблемой. Но волшебных пуль нет — в общем, обработка 2 ГБ текста построчно с регулярным выражением в Python, вероятно, будет выполняться за минуты, а не секунды.

Вот тестовый скрипт, который покажет, сколько времени требуется, чтобы прочитать файл, строка за строкой, и больше ничего не делать:

from datetime import datetime

start = datetime.now()
for line in open("big_honkin_file.dat"):
    pass
end = datetime.now()
print (end-start)
person PaulMcG    schedule 29.08.2013
comment
Спасибо за ответ, Пол. На самом деле я новичок в python. Я использую это в одном из своих проектов. поэтому не могли бы вы сказать мне, сколько времени обычно потребуется, чтобы прочитать большой файл (скажем, 2 ГБ) построчно и распечатать его? а также как узнать, что регулярное выражение эффективно. Если вы можете предоставить несколько хороших ссылок по этому поводу, это тоже хорошо. - person user2109788; 29.08.2013
comment
@ user2109788 - вы узнаете больше, написав этот простой тестовый скрипт самостоятельно. Почему бы не раз самый простой контрольный случай? Напишите скрипт, который читает файл построчно, пока ничего не делайте. Посмотрите, сколько времени это займет. Затем откройте выходной файл и запишите прочитанную строку в выходной файл. Посмотрите, сколько времени это займет. Эти небольшие тесты должны дать вам некоторое представление о том, какой будет нижняя граница для вашей программы регулярных выражений. Что касается улучшения самого регулярного выражения, поищите в Google производительность регулярных выражений, и вы получите ряд полезных статей по этому вопросу. - person PaulMcG; 29.08.2013