2015-12-10 4 views
1

Я новичок в написании сценариев и читал на Python около 6 недель. Нижеследующее предназначено для чтения файла журнала и отправки предупреждения, если найдено одно из ключевых слов, определенных в srchstring. Он работает так, как ожидалось, и не предупреждает о найденных ранее строках, как и ожидалось. Однако файл, обрабатывающий его, активно записывается приложением, а скрипт слишком медленный в файлах размером около 500 Мб. до 200 мб работает отлично, т. е. в течение 20 секунд. Может ли кто-нибудь предложить более эффективный способ поиска строки в файле на основе предварительно определенного списка?Эффективный способ найти строку по списку

import os 
srchstring = ["Shutdown", "Disconnecting", "Stopping Event Thread"] 

if os.path.isfile(r"\\server\\share\\logfile.txt"): 
with open(r"\\server\\share\\logfile.txt","r") as F: 
    for line in F: 
     for st in srchstring: 
      if st in line: 
       print line, 
       #do some slicing of string to get dd/mm/yy hh:mm:ss:ms 
       # then create a marker file called file_dd/mm/yy hh:mm:ss:ms 
       if os.path.isfile("file_dd/mm/yy hh:mm:ss:ms"): # check if a file already exists named file_dd/mm/yy hh:mm:ss:ms 
        print "string previously found- ignoring, continuing search" # marker file exists 
       else: 
        open("file_dd/mm/yy hh:mm:ss:ms", 'a') # create file_dd/mm/yy hh:mm:ss:ms 
        print "error string found--creating marker file sending email alert" # no marker file, create it then send email 

else: 
    print "file not exist" 
+0

Выполняется ли этот код? Что такое 'F'? Я предполагаю, что это файл, который вы читаете, но код не отражает этого. Кроме того, когда вы открываете файл для записи, вы его не закрываете. Питонический способ записи в файлы использует контекст: 'with open ('filename') как f: ...'. На ваш вопрос, я бы попробовал использовать 'set' вместо' list' для 'srchstring'. Затем для каждой строки в файле создайте 'set' слов в строке (например,' linset = set (line.split ('')) ') и пересечение набора настроек (см. Https: // docs. python.org/2/library/sets.html). Если он не пуст, значит, есть совпадение. Я предполагаю, что это может ускорить работу. – jorgeh

+0

Откуда вы знаете, что накладные расходы происходят из поиска 'in'? Возможно, вы читаете весь файл в памяти, но вы не показываете этот код. Откуда берется «F»? – cdarke

+1

Извинения, я пропустил линию, когда редактировал сообщение для правильного форматирования. Я обновил его сейчас. Я где-то читал, что вложенное «если» не может быть лучшим способом, но я не могу найти сообщение, которое это предлагало. Именно это заставило меня поверить в то, что IF может быть узким местом. – toon

ответ

0

Предполагаю, что вы используете Linux. Если вы этого не сделаете, установите MinGW на Windows, и решение ниже также станет подходящим.

Просто оставьте твердую часть доступными наиболее эффективными инструментами. Отфильтруйте данные перед тем, как перейти к скрипту python. Используйте grep команду, чтобы получить строки, содержащие "Shutdown", "Disconnecting" или "Stopping Event Thread"

grep 'Shutdown\|Disconnecting\|"Stopping Event Thread"' /server/share/logfile.txt 

и перенаправлять строки в скрипт

grep 'Shutdown\|Disconnecting\|"Stopping Event Thread"' /server/share/logfile.txt | python log.py 

Edit: решение для Windows. Вы можете создать файл .bat, чтобы сделать его исполняемым.

findstr /c:"Shutdown" /c:"Disconnecting" /c:"Stopping Event Thread" \server\share\logfile.txt | python log.py 

В «log.py», читайте с stdin. Это файловый объект, поэтому никаких трудностей здесь нет:

import sys 

for line in sys.stdin: 
    print line, 
    # do some slicing of string to get dd/mm/yy hh:mm:ss:ms 
    # then create a marker file called file_dd/mm/yy hh:mm:ss:ms 
    # and so on 

Это решение уменьшит объем работы, которую должен выполнять ваш скрипт. Поскольку Python не является быстрым языком, он может ускорить выполнение задачи. Я подозреваю, что его можно переписать только в bash, и он будет еще быстрее (20 + лет оптимизации программы C - это не то, с чем вы легко конкурируете), но я не знаю, что такое bash.

+0

@toon все равно, подход все еще действителен. 'grep' переносится в окна несколько раз (я предлагаю его получить, установив пакет MinGW), а Windows имеет свои собственные инструменты' find' и 'findstr'. В ближайшее время я обновлю сообщение с помощью аналога Windows, если найду подходящее. – Vovanrock2002

+0

Почему вы говорите, что Python не быстрый? Для языка сценариев он достаточно хорошо оптимизирован для чтения ввода по одной строке за раз. Однако оставшийся скрипт Python довольно глупый. – tripleee

+0

Почему это глупо? часть поиска не такая уж трудная, но повторное чтение файла и игнорирование строки, которая ранее была найдена, может быть сложной для начинающего – toon

1

Рефакторинг выражения поиска в предварительно скомпилированном регулярном выражении позволяет избежать (явного) внутреннего цикла.

import os, re 
regex = re.compile(r'Shutdown|Disconnecting|Stopping Event Thread') 

if os.path.isfile(r"\\server\\share\\logfile.txt"): 
    #Indentation fixed as per comment 
    with open(r"\\server\\share\\logfile.txt","r") as F: 
     for line in F: 
      if regex.search(line): 
       # ... 
+0

с помощью regex увеличил скорость поиска> 10 Я оцениваю - спасибо – toon

+0

actaully Я, возможно, был поспешным, как работает, когда файл записывается приложением, возвращает только более быстрые результаты. Когда файл не записывается в регулярное выражение быстрее, спасибо. – toon

Смежные вопросы