2017-06-02 41 views
0

我有一個Excel 2010文件(xlsx)的列表,需要搜索一個特定的值。由於xslx是二進制格式,因此無法使用普通文本編輯器完成。所以我做的每個文件蟒蛇多處理工作者內存消耗無限增加

  1. 獲取文件名
  2. 在大熊貓開放
  3. 轉換數據框以下,以numpy的陣列
  4. 的價值

這需要多處理,因爲它校驗陣列不是I/O限制的。熊貓的東西和數組轉換需要時間。所以我建立了一個我的腳本的多處理版本(見下面):

問題是每個工作進程的內存消耗。雖然每個xlsx文件只有100kb,但每個工作人員可以創建2GB的連續峯值。我不明白爲什麼在處理新文件之前未釋放內存。這種方式在處理文件列表之前耗盡內存。

這個問題似乎不是隊列,而是熊貓的東西。

這是我的代碼。它可以用你係統上的任何xlsx文件進行測試。

import pandas as pd 
import multiprocessing as mp 
import glob 

path = r'c:\temp' 
fileFilter = 'serial.xlsx' 
searchString = '804.486' 


def searchFile(tasks, results, searchString): 
    """Iterates over files in tasks and searches in file for the 
    occurence of 'searchString'. 

    Args: 
    ----- 
    tasks: queue of strings 
     Files to look in 
    results: queue of strings 
     Files where the searchString was found 
    searchString: str 
     the string to be searched 
    """ 
    # for files in the queue 
    for task in iter(tasks.get, 'STOP'): 
     # read the filestructre into memory 
     xfile = pd.ExcelFile(task) 
     # iterate all sheets 
     for sheet in xfile.sheet_names[:3]: 
      # read the sheet 
      data = pd.read_excel(xfile, sheet) 
      # check if searchString is in numpy representation of dataframe 
      if searchString in data.values.astype(str): 
       # put filename in results queue 
       results.put(task) 
       break 
     xfile.close() 

if __name__ == "__main__": 
    # get all files matching the filter that are in the root path 
    print('gathering files') 
    files = glob.glob(path + '\**\{}'.format(fileFilter), recursive=True) 

    # setup of queues and variables 
    n_proc = 2 
    tasks = mp.Queue() 
    results = mp.Queue() 

    print('Start processing') 
    # setup processes and start them 
    procs = [mp.Process(target=searchFile, 
         args=(tasks, results, searchString)) 
      for x in range(n_proc)] 
    for p in procs: 
     p.daemon = True 
     p.start() 

    # populate queue 
    for file in files: 
     tasks.put(file) 

    for proc in procs: 
     tasks.put('STOP') 

    for p in procs: 
     p.join() 

    # print results 
    for result in range(results.qsize()): 
     print(results.get()) 

    print('Done') 
+0

作爲備註 - 「.xlsx」文件是zip壓縮的歸檔文件,其中帶有xml。如果您唯一需要的是搜索一個值,您可以解壓並在沒有任何額外模塊的情況下搜索流。 –

+0

這不是唯一要做的事情....我可以使用python內部zip模塊解壓縮它們嗎? – RaJa

+0

試圖解壓縮xlsx文件,並且它會生成許多xml文檔:對於樣式,對於每個工作表,主題......用這些值查找xml文檔相當困難。 – RaJa

回答

0

似乎gc中的問題,它不能收集你永遠不會離開的函數上下文中的熊貓框架。您可以使用multiprocessing.Pool.map,它可以爲您執行隊列處理。每個項目都會調用Worker函數,讓gc完成這項工作。您也可以使用maxtasksperchild Pool構造函數參數來限制worker處理的項目數量。

import glob 
import multiprocessing 


def searchFile(task, searchString): 
    xfile = pd.ExcelFile(task) 
    ... 
    if found: 
     return task 


if __name__ == '__main__': 
    files = glob.glob(path + '\**\{}'.format(fileFilter), recursive=True) 
    searchString = '804.486' 

    pool = multiprocessing.Pool(2, maxtasksperchild=10) 

    args = ((fname, searchString) for fname in files) 
    matchedFiles = filter(None, pool.map(searchFile, args)) 
    pool.close() 
+0

試過這個...沒有解決問題,因爲問題不是代碼,而是其中的一個文件。檢查了一組不同的文件,它沒有問題。不管怎麼說,還是要謝謝你。 – RaJa