2010-08-31 3 views
2

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

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

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

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/[email protected]:21 
2010-08-06 00:00:00,040 DEBUG [] com.thg.sam.email.EmailUtils.sendEmail:206 - [email protected] 
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/[email protected]:21 
+0

Можете ли вы поместить код с помощью маркера кода. отступы теряются. – pyfunc

+0

Как действительно базовая проверка здравомыслия, можете ли вы подтвердить, что у вас все еще есть проблема, если вы вставляете 'r' непосредственно перед строковой константой для регулярного выражения? то есть 're.compile (r '....') 'Это гарантирует, что все ваши обратные слэши будут видны компилятором regexp вместо того, чтобы быть съеденным парсером Python. – zwol

+0

С одной стороны, в строке 'infile = C: \ Python \\ ...' вам не хватает одной обратной косой черты после 'C: \'. Всегда лучше использовать '/' для разделителя путей, поскольку это работает практически на всех платформах без необходимости экранирования. –

ответ

2

Ваша проблема, безусловно, часть @paulrubel отметил:

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

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

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

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

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

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

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

0

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

Edit: Пример использования: PDB

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

Run этот сценарий, и вы получите что-то вроде следующего:

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) и т. Д.

+0

Не уверен, что я понимаю? Как я уже сказал, я новичок в python, вы можете отправить пример? – Bill

+0

@Bill Я добавлю ссылку на этот ответ. – MatrixFrog

0

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

import fileinput 
for line in fileinput.input([infile]): 
    lookup = re.search(match, line) 
    # etc. 
+0

Если вы можете уточнить, потому что в ходе моего исследования мне сказали, что 'для строки в имени файла:' - лучший способ, но если вы можете предоставить мне, почему выше это лучше, я обязательно его использую. – Bill

+0

@Bill, никоим образом 'fileinput' будет лучше, чем ваш цикл (вы просто назовете свои переменные по-настоящему странным образом, но в то время как это затрудняет понимание вашего кода, это не должно влиять на его семантику ;-). –

+0

с точки зрения производительности. Я постараюсь загрузить файл завтра и посмотреть, что я придумал. Я не могу проверить его, так как мой код не работает в указанной строке. – Bill

7

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

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

((\w+).?)+: 

Представьте себе строку, которая не имеет: в ней, но довольно длинная. Вы окажетесь в мире обратного отслеживания, поскольку regexp пытается КАЖДОЕ сочетание способов разделения словных символов между \ w и. и THEN пытается группировать их всеми возможными способами. Если вы можете быть более конкретным в своем шаблоне, он окупится большим временем.

1

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

lookup = re.search(match,line) 

должен быть

lookup = match.search(line) 

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

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

Обновление:

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

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

Вы можете использовать re.match из документов: http: //docs.python.org/library/re.html re.match (pattern, string [, flags]) ¶ Если на начало строки соответствует шаблону регулярного выражения, возвращает соответствующий экземпляр MatchObject. Возврат Нет, если строка не соответствует шаблону; обратите внимание, что это отличается от совпадения нулевой длины. –

+0

Спасибо за это. Я сделал это, но моя проблема все еще возникает, но по крайней мере я улучшаю ее код! Я пытаюсь просмотреть комментарии и добавить больше подробностей, если смогу. – Bill

1

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

Возможно, проще и быстрее найти фиксированный шаблон на каждой линии.

if '_SEARCH:' in line: 
    print line 
    count += 1 
+0

+1. Кажется, что OP использует регулярное выражение как своего рода сложный парсер, который, вероятно, является чрезмерным, учитывая, что данные выглядят в довольно последовательном формате. – Brian

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