2017-07-04 101 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