2017-06-02 11 views
0

特定の値を検索する必要があるExcel 2010ファイル(xlsx)のリストがあります。 xslxはバイナリ形式なので、通常のテキストエディタでは実行できません。だから私は、コンバートデータフレームは、これはそれとして、マルチプロセッシングのために呼び出しますnumpyの配列 Pythonマルチプロセッシングワーカーのメモリ消費が無期限に増加する

  • 用のチェック配列

    にパンダ

  • にオープン
    1. ファイルごとに次のgetファイル名を行いますI/Oにバインドされていません。パンダのものやアレイの変換には時間が必要です。そこで私はスクリプトのマルチプロセッシングバージョンをセットアップしました(下記参照)。

      問題は各ワーカープロセスのメモリ消費です。各xlsxファイルはわずか100kbですが、1人の作業者あたり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'ファイルは、xmlを内部に持つZip圧縮アーカイブです。必要なのは、値を検索するだけであれば、余分なモジュールを使わずにストリームを解凍して検索することができます。 –

    +0

    これは唯一のことではありません....私はpythonの内部zipモジュールで解凍できますか? – RaJa

    +0

    xlsxファイルを解凍しようとしましたが、多くのxml文書を生成します:スタイル、各ワークシート、テーマ、... xml文書を値で見つけることはかなり困難です。 – RaJa

    答えて

    0

    GCで問題だ、あなたが離れることはない関数コンテキストにおけるパンダフレームを集めることができません。キュー処理を行うことができるmultiprocessing.Pool.mapを使用することができます。作業者関数がすべての項目に対して呼び出され、gcにジョブを実行させます。また、maxtasksperchildプールコンストラクタparamを使用して、ワーカーが処理するアイテムの量を制限することもできます。

    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

    関連する問題