2

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

有没有更好的方法来做我在下面做的任何事情?我的目标是读取文件(如果您需要我将其发送给您,我可以 15MB 文本日志)根据正则表达式查找匹配项并打印匹配行。还会有更多,但这就是我所得到的。我正在使用 python 2.6

任何想法都会有所帮助,也可以编写代码注释!我是一个 python 菜鸟,还在学习。

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
4

6 回答 6

7

给您带来麻烦的输入行是什么样的?我会尝试打印出来。我怀疑你的 CPU 在运行时是固定的。

嵌套的正则表达式,就像你有的那样,当它们不能快速匹配时,它们的性能可能会很差

((\w+).?)+:

想象一个没有 : 但相当长的字符串。当正则表达式尝试各种方法来分隔 \w 和 . 然后尝试以各种可能的方式对它们进行分组。如果您可以更具体地了解您的模式,它将获得巨大的回报。

于 2010-09-01T00:26:15.493 回答
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——甚至不需要原子组。

于 2010-09-01T08:50:41.643 回答
1

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

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

if '_SEARCH:' in line:
    print line
    count += 1
于 2010-09-01T18:28:04.173 回答
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
于 2010-09-01T00:36:54.063 回答
0

无论如何,这可能是一个内存问题。对于大文件,最好使用该fileinput模块,如下所示:

import fileinput
for line in fileinput.input([infile]):
    lookup = re.search(match, line)
     # etc.
于 2010-09-01T00:12:28.383 回答
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)等。

于 2010-09-01T00:05:56.727 回答