Почему мой код останавливается? - PullRequest
2 голосов
/ 01 сентября 2010

Эй, я столкнулся с проблемой, из-за которой моя программа перестает перебирать файл в записи 57802 по какой-то причине, которую я не могу понять. Я поместил секцию сердцебиения, чтобы я мог видеть, на какой линии он находится, и это помогло, но теперь я застрял в том, почему это останавливается здесь. Я думал, что это проблема с памятью, но я просто запустил ее на своем компьютере с памятью 6 ГБ, и он все равно остановился.

Есть ли лучший способ сделать что-нибудь, что я делаю ниже? Моя цель - прочитать файл (если вам нужно, чтобы я отправил его вам, я могу 15 МБ текстового журнала) найти соответствие на основе выражения регулярного выражения и вывести соответствующую строку. Еще не все, но это насколько я получил. Я использую Python 2.6

Любые идеи также помогут и закодировать комментарии! Я питон нуб и все еще учусь.

import sys, os, os.path, operator
import re, time, fileinput

infile = os.path.join("C:\\","Python26","Scripts","stdout.log")

start = time.clock()

filename  = open(infile,"r")

match = re.compile(r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}),\d{3} +\w+ +\[([\w.]+)\] ((\w+).?)+:\d+ - (\w+)_SEARCH:(.+)')

count = 0
heartbeat = 0
for line in filename:
    heartbeat = heartbeat + 1
    print heartbeat
    lookup = match.search(line)
    if lookup:
        count = count + 1
        print line
end = time.clock()
elapsed = end-start
print "Finished processing at:",elapsed,"secs. Count of records =",count,"."

filename.close()

Это строка 57802, где она терпит неудачу:

2010-08-06 08:15:15,390 DEBUG [ah_admin] com.thg.struts2.SecurityInterceptor.intercept:46 - Action not SecurityAware; skipping privilege check.

Это совпадающая строка:

2010-08-06 09:27:29,545 INFO  [patrick.phelan] com.thg.sam.actions.marketmaterial.MarketMaterialAction.result:223 - MARKET_MATERIAL_SEARCH:{"_appInfo":{"_appId":21,"_companyDivisionId":42,"_environment":"PRODUCTION"},"_description":"symlin","_createdBy":"","_fieldType":"GEO","_geoIds":["Illinois"],"_brandIds":[2883],"_archived":"ACTIVE","_expired":"UNEXPIRED","_customized":"CUSTOMIZED","_webVisible":"VISIBLE_ONLY"}

Пример данных только первые 5 строк:

2010-08-06 00:00:00,035 DEBUG [] com.thg.sam.jobs.PlanFormularyLoadJob.executeInternal:67 - Entered into PlanFormularyLoadJob: executeInternal
2010-08-06 00:00:00,039 DEBUG [] com.thg.ftpComponent.service.JScapeFtpService.open:153 - Opening FTP connection to sdrive/hibbert@tccfp01.hibbertnet.com:21
2010-08-06 00:00:00,040 DEBUG [] com.thg.sam.email.EmailUtils.sendEmail:206 - org.apache.commons.mail.MultiPartEmail@446e79
2010-08-06 00:00:00,045 DEBUG [] com.thg.sam.services.OrderService.getOrdersWithStatus:121 - Orders list size=13
2010-08-06 00:00:00,045 DEBUG [] com.thg.ftpComponent.service.JScapeFtpService.open:153 - Opening FTP connection to sdrive/hibbert@tccfp01.hibbertnet.com:21

Ответы [ 6 ]

7 голосов
/ 01 сентября 2010

Как выглядит строка ввода, которая доставляет вам неприятности?Я бы попробовал распечатать это.Я подозреваю, что ваш процессор привязан, пока он работает.

Вложенные регулярные выражения, как у вас, могут иметь ОЧЕНЬ плохую производительность, когда они не совпадают быстро.

((\w+).?)+:

Представьте строку, которая не имеет:в нем, но довольно долго.Вы окажетесь в мире возврата, так как регулярное выражение пытается КАЖДУЮ комбинацию способов разделить символы слова между \ w и.И ТОГДА пытается сгруппировать их всеми возможными способами.Если вы можете быть более конкретным в своем паттерне, это окупится.

2 голосов
/ 01 сентября 2010

Ваша проблема - определенно та часть, на которую указал @paulrubel:

((\w+).?)+:\d+

Теперь, когда вы добавили пример данных, очевидно, что . должен соответствовать буквальной точке, что означает, что выдолжен был избежать этого (\.).Кроме того, вам не нужен внутренний набор скобок, и внешний набор не должен захватывать, но это основная структура, которая убивает вас;слишком много вариантов расположения слов и точек, которые нужно попробовать, прежде чем сдаться.Все остальные строки терпят неудачу, прежде чем эта часть регулярного выражения пытается, поэтому у вас нет проблем с ними.

Когда я пробую это в RegexBuddy, ваше регулярное выражение соответствует хорошей линии в 186 шагах,и прекращает попытки по линии 57802 после 1000000 шагов.Когда я выхожу из точки, для хорошей линии требуется только 90 шагов, но она все равно истекает в строке 57802. Но теперь я знаю, что часть регулярного выражения может соответствовать только символам и точкам слова.Как только он поглотит все, что может, следующий бит должен соответствовать :\d+;если это не так, я знаю, что нет смысла пробовать другие меры.Я могу использовать атомарную группу, чтобы не беспокоить:

(?>(?:\w+\.?)+):\d+

С этим изменением хорошая линия совпадает за 83 шага, а строка 57802 делает только 66 шагов, чтобы сообщить об ошибке.Но не всегда возможно использовать атомарные группы, поэтому вы должны попытаться привести свое регулярное выражение в соответствие с фактической структурой текста, которому он соответствует.В этом случае вы сопоставляете то, что выглядит как имя класса Java (некоторые символы слова, за которыми следует ноль или более экземпляров (точка и еще несколько символов слова)), за которыми следует двоеточие и номер строки:

\w+(?:\.\w+)*:\d+

Когда я вставляю это в регулярное выражение, оно совпадает с хорошей линией за 80 шагов и отклоняет строку 57802 за 67 шагов - атомная группа даже не нужна.

1 голос
/ 01 сентября 2010

Ваш шаблон содержит фиксированную строку SEARCH_ и кучу сложных выражений (включая захваты), которые действительно собираются отбить движок регулярных выражений ... но вы ничего не делаете с захваченным текстом, поэтому все, что вы хотите знать, этоэто совпадает?

Может быть проще и быстрее просто искать фиксированный шаблон в каждой строке.

if '_SEARCH:' in line:
    print line
    count += 1
1 голос
/ 01 сентября 2010

вы скомпилировали свое регулярное выражение, но никогда не использовали его?

lookup = re.search(match,line)

должно быть

lookup = match.search(line)

и вы должны использовать os.path.join()

infile = os.path.join("C:\\","Python26","Scripts","stdout.log")

Обновление:

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

for line in open("stdout.log"):
    s = line.split()
    D,T=s[0],s[1]
    # use the time module and strptime to check valid date/time
    # or you can split "-" on D and T and do manual check using > or < and math
0 голосов
/ 01 сентября 2010

В любом случае это может быть проблема с памятью.С большими файлами, вероятно, лучше использовать модуль fileinput, например:

import fileinput
for line in fileinput.input([infile]):
    lookup = re.search(match, line)
     # etc.
0 голосов
/ 01 сентября 2010

Попробуйте использовать pdb .Если вы введете pdb.set_trace() в свое сердцебиение незадолго до его остановки, вы можете посмотреть на конкретную строку, на которой он останавливается, и посмотреть, что каждая из ваших строк кода делает с этой строкой.

Редактировать: пример pdbиспользуйте:

import pdb
for i in range(50):
    print i
    if i == 12:
        pdb.set_trace()

Запустите этот скрипт, и вы получите что-то вроде следующего:

0
1
2
3
4
5
6
7
8
9
10
11
12
> <stdin>(1)<module>()
(Pdb)

Теперь вы можете оценивать выражения Python из контекста i = 12.

(Pdb) print i
12

Используйте это, но поместите pdb.set_trace() в свой цикл после увеличения сердцебиения, если heartbeat == 57802.Затем вы можете распечатать строку с p line, результат поиска по регулярному выражению с p match.search(line) и т. Д.

...