2017-07-04 103 views
0

我的函数按以下方式逐行处理文件。 定义了多种错误模式,并且需要应用到每一行。 我使用multiprocessing.Pool来处理块中的文件。Python re.match递归调用内存泄漏

1G文件的内存使用量增加到2G。 即使在文件处理后仍保持在2G。 文件最后关闭。

如果我注释掉re_pat.match的调用,内存使用情况正常,并且保持在100Mb以下。

我是否以错误的方式使用re? 我找不出解决内存泄漏的方法。

def line_match(lines, errors) 
    for error in errors: 
     try: 
      re_pat = re.compile(error['pattern']) 
     except Exception: 
      print_error 
      continue 

     for line in lines: 
      m = re_pat.match(line) 
      # other code to handle matched object 



def process_large_file(fo): 
    p = multiprocessing.Pool() 
    while True: 
     lines = list(itertools.islice(fo, line_per_proc)) 
     if not lines: 
      break 
     result = p.apply_async(line_match, args=(errors, lines)) 

注: 我省略了一些代码,因为我觉得显著的区别是有/无re_pat.match(...)

+1

你的代码到底在做什么?目前还不清楚。 –

+0

@cᴏʟᴅsᴘᴇᴇᴅ我更新了代码缩进。它将错误模式列表应用到文件的每一行以查找匹配的对象。 – Mayling

+0

快速问题。什么是'线'?它从何而来? –

回答

0

几件事情......看看的使用itertools.islice在这里。你必须指定一个开始和停止参数。这似乎并不像你这样做。每个进程都在文件的同一行上工作,也不要将其转换为列表,因为您不需要一次全部执行 - 这是浪费。

你需要做这样的事情:

line_per_proc = ... 

count = 0 
while True: 
    lines = itertools.islice(fo, start=line_per_proc, stop=lines_per_proc * (count + 1)) 
    if not lines: 
     break 
    result = p.apply_async(line_match, args=(errors, lines)) 
    count += 1 

接下来,对于每个模式,您遍历lines。所以,如果你有10个模式,你可以迭代10次!如果你有一个大文件,这是特别低效的,特别是当这些行被加载为列表时!

试试这个:

def line_match(lines, errors): 
    # first, compile all your patterns 
    compiled_patterns = [] 
    for error in errors: 
     compiled_patterns.append(re.compile(error['pattern'])) 

    for line in lines: # lines is a generator, not a list 
     for pattern in compiled_patterns: 
      m = pattern.match(line) 
      # other code to handle matched object 

这可帮助您开始使用一个完整的解决方案。

+0

谢谢。我使用列表,因为我需要行上下文。 (我会引用你的代码来优化我的代码)。我尝试了你的方法,无法解决内存泄漏问题的模式列表。我很确定这个漏洞发生在pattern.match里面。 – Mayling

+0

@Mayling好的......你可能会发现绕过编译过程并使用模块级别的re.match等价物很有用。尝试一下。 –

+0

@COLDSPEED,谢谢。我试过了。它使用更多的内存,速度更慢。 – Mayling