为什么我的代码会停止?

时间:2010-08-31 23:58:50

标签: python regex string-matching

嘿我遇到了一个问题,我的程序停止在57802记录中迭代文件由于某些原因我无法弄清楚。我放了一个心跳部分,所以我可以看到它在哪条线上并且它有所帮助,但现在我被困在为什么它停在这里。我认为这是一个内存问题,但我只是在我的6GB内存计算机上运行它仍然停止。

有没有更好的方法来做我在下面做的任何事情? 我的目标是阅读文件(如果你需要我发送给你我可以15MB文本日志) 根据正则表达式找到匹配项并打印匹配的行。还有更多,但就我而言。我正在使用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 个答案:

答案 0 :(得分:7)

给您带来麻烦的输入线是什么样的?我试着打印出来。我怀疑你的CPU在运行时是挂钩的。

嵌套的正则表达式与您一样,如果它们不能很快匹配,可能会有VERY性能不佳。

((\w+).?)+:

想象一个字符串,其中没有:但是相当长。你将最终进入一个回溯的世界,因为正则表达式试图在\ w和\ n之间分隔单词字符的各种方法组合。然后尝试以各种可能的方式对它们进行分组。如果你可以在你的模式中更具体,它将带来丰厚的回报。

答案 1 :(得分:2)

你的问题绝对是@paulrubel指出的部分:

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

现在你已经添加了样本数据,很明显.应该与文字点匹配,这意味着你应该对其进行转义(\.)。此外,你不需要内部括号集,外部集应该是非捕获的,但它是杀死你的基本结构;在放弃之前必须尝试的字符和点的排列太多。在尝试使用正则表达式的部分之前,其他所有行都会失败,这就是为什么你没有任何问题。

当我在RegexBuddy中尝试时,你的正则表达式在186步中匹配好线,并且在1,000,000步之后放弃尝试57802行。当我逃离点时,好的线只需要90步才能匹配,但它仍然在57802线上超时。但现在我知道正则表达式的一部分只能匹配单词字符和点。一旦它消耗了所有这些,下一位必须匹配:\d+;如果没有,我知道尝试其他安排是没有意义的。我可以使用原子组告诉它不要打扰:

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

通过该更改,好的行匹配83个步骤,而行57802只需66个步骤来报告失败。但是使用原子组并不总是可行的,所以你应该尝试使你的正则表达式符合它匹配的文本的实际结构。在这种情况下,您将匹配看起来像Java类名称的内容(一些单词字符,后跟零个或多个(一个点和一些单词字符)的实例),后跟冒号和行号:

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

当我将其插入正则表达式时,它会在80个步骤中匹配好行,并在67个步骤中拒绝行57802 - 甚至不需要原子组。

答案 2 :(得分:1)

你编译了你的正则表达式但从未使用它?

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

答案 3 :(得分:1)

你的模式包含固定的字符串SEARCH_和一堆复杂的表达式(包括捕获),这些表达式确实会破坏正则表达式引擎..但你不会对捕获的文本做任何事情,所以你只想知道'是它匹配吗?'

在每一行上搜索固定模式可能更简单快捷。

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

答案 4 :(得分:0)

尝试使用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)

现在,您可以从i = 12的上下文中评估Python表达式。

(Pdb) print i
12

使用它,但在增加心跳后将pdb.set_trace()放在循环中,如果heartbeat == 57802。然后,您可以使用p line打印一行,使用p match.search(line)进行正则表达式搜索的结果等。

答案 5 :(得分:0)

无论如何,它可能是一个记忆问题。对于大文件,最好使用fileinput模块,而不是像这样:

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