2016-10-13 3 views
1

私は大量のファイルを持っているため、それらをトラバースして文字列を検索する必要があります。フォルダ、それ以外の場合は閉じます。新しいクラスのファイルを大量に読み込んで閉じるとOSErrorが発生する:開いているファイルが多すぎる

import os 
import stringsfilter 


def apply_filter(path, filter_dict): 
    dirlist = os.listdir(path) 
    for directory in dirlist: 
     pwd = path + '/' + directory 
     filelist = os.listdir(pwd) 
     for filename in filelist: 
      if filename.split('.')[-1] == "stats": 
       sfilter = stringsfilter.StringsFilter(pwd, filename, filter_dict["strings"]) 
       sfilter.find_strings_and_move() 

、ここstringsfilter.pyである:ここで

は、サンプルコードがある

import main 
import codecs 
import os 
import shutil 


class StringsFilter: 

    strings = None 

    def __init__(self, filepath, filename, strings): 
     self.filepath = filepath 
     self.filename = filename 
     self.strings = strings 
     self.logger = main.get_module_logger("StringsFilter") 
     self.file_desc = codecs.open(self.filepath + '/' + self.filename, 'r', encoding="utf-8-sig") 
     self.logger.debug("[-] Strings: " + str(self.strings)) 
     self.logger.debug("[-] Instantiating class Strings Filter, filename: %s " % self.filename) 

    def find_strings_and_move(self): 
     for line in self.file_desc.readlines(): 
      for string in self.strings: 
       if string in line: 
        self.move_to_folder() 
        return 
     self.close() 

    def move_to_folder(self): 
     name = self.filename.split('.')[0] 
     os.mkdir(self.filepath + '/' + name) 
     shutil.copyfile(self.filepath + '/' + self.filename, 
         self.filepath + '/' + name + '/' + self.filename) 
     self.close() 

    def close(self): 
     if self.file_desc: 
      self.logger.debug("[-] Closing file %s" % self.filename) 
      self.file_desc.close() 

はmain.py:ログに

import logging 

def get_module_logger(name): 
    # create logger 
    logger = logging.getLogger(name) 

    # set logging level to log everything 
    logger.setLevel(logging.DEBUG) 

    # create file handler which logs everything 
    fh = logging.FileHandler('files.log') 
    fh.setLevel(logging.DEBUG) 

    # create console handler 
    ch = logging.StreamHandler() 
    ch.setLevel(logging.INFO) 

    # create formatter and add it to the handlersi 
    formatter = logging.Formatter('[%(asctime)s] [%(name)-17s] [%(levelname)-5s] - %(message)s') 
    fh.setFormatter(formatter) 
    ch.setFormatter(formatter) 

    # add the handlers to the logger 
    logger.addHandler(fh) 
    logger.addHandler(ch) 
    return logger 

私は、以下を参照してくださいすることができます

[2016-10-13 10:07:07,002] [StringsFilter ] [DEBUG] - [-] Strings: ['DEVICE_PROBLEM'] 
[2016-10-13 10:07:07,002] [StringsFilter ] [DEBUG] - [-] Instantiating class Strings Filter, filename: file1.stats 
[2016-10-13 10:07:07,003] [StringsFilter ] [DEBUG] - [-] Closing file file1.stats 
[2016-10-13 10:07:07,003] [StringsFilter ] [DEBUG] - [-] Strings: ['DEVICE_PROBLEM'] 
[2016-10-13 10:07:07,003] [StringsFilter ] [DEBUG] - [-] Strings: ['DEVICE_PROBLEM'] 
[2016-10-13 10:07:07,004] [StringsFilter ] [DEBUG] - [-] Instantiating class Strings Filter, filename: file2.stats 
[2016-10-13 10:07:07,004] [StringsFilter ] [DEBUG] - [-] Instantiating class Strings Filter, filename: file2.stats 
[2016-10-13 10:07:07,004] [StringsFilter ] [DEBUG] - [-] Closing file file2.stats 
[2016-10-13 10:07:07,004] [StringsFilter ] [DEBUG] - [-] Closing file file2.stats 
[2016-10-13 10:07:07,005] [StringsFilter ] [DEBUG] - [-] Strings: ['DEVICE_PROBLEM'] 
[2016-10-13 10:07:07,005] [StringsFilter ] [DEBUG] - [-] Strings: ['DEVICE_PROBLEM'] 
[2016-10-13 10:07:07,005] [StringsFilter ] [DEBUG] - [-] Strings: ['DEVICE_PROBLEM'] 
[2016-10-13 10:07:07,005] [StringsFilter ] [DEBUG] - [-] Instantiating class Strings Filter, filename: file3.stats 
[2016-10-13 10:07:07,005] [StringsFilter ] [DEBUG] - [-] Instantiating class Strings Filter, filename: file3.stats 
[2016-10-13 10:07:07,005] [StringsFilter ] [DEBUG] - [-] Instantiating class Strings Filter, filename: file3.stats 
[2016-10-13 10:07:07,006] [StringsFilter ] [DEBUG] - [-] Closing file file3.stats 
[2016-10-13 10:07:07,006] [StringsFilter ] [DEBUG] - [-] Closing file file3.stats 
[2016-10-13 10:07:07,006] [StringsFilter ] [DEBUG] - [-] Closing file file3.stats 

そして、それは上で行く、そこに非常に多くのファイルが開いていて、プログラムが

OSError: [Errno 24] Too many files open 

で終了するまで反復ごとに、のinitから各ステートメントは、再び行われるように私は理解できないようですのステートメントは、インスタンスが作成されるたびに複数回呼び出されます。あなたが同じことを持っている理由

+0

'「メイン」はエラーを取得stringsfilter.py''で9行目でdefined'されていません。 –

+0

大変申し訳ございません。それは今追加されます。 – Libor

答えて

0

理由は複数回ログイン: main.get_module_logger("StringsFilter")が呼び出されるたびに、あなたが1つのロガーに複数のハンドラを取得するので、あなたは、logging.getLogger(name)から返された同じロガーにlogger.addHandler(...)を呼び出します。より良い開いているファイルについては、モジュールレベルロガー

import ... 
LOG = main.get_module_logger("StringsFilter") 
class StringsFilter:... 

作る、私はその理由を参照してください、しかしfind_strings_and_move()with open(filename) as f:構文を使用することを検討していません。移動2前

LOG = main.get_module_logger("StringsFilter") 
class StringsFilter: 

    strings = None 

    def __init__(self, filepath, filename, strings): 
     self.filepath = filepath 
     self.filename = filename 
     self.strings = strings 
     LOG.debug("[-] Strings: " + str(self.strings)) 
     LOG.debug("[-] Instantiating class Strings Filter, filename: %s " % self.filename) 

    def find_strings_and_move(self): 
     with open(self.filepath + '/' + self.filename, 'r') as file_desc: 
      lines = file_desc.readlines() 
     for line in lines: 
      for string in self.strings: 
       if string in line: 
        self.move_to_folder() 
        return 

    def move_to_folder(self): 
     name = self.filename.split('.')[0] 
     os.mkdir(self.filepath + '/' + name) 
     shutil.copyfile(self.filepath + '/' + self.filename, 
         self.filepath + '/' + name + '/' + self.filename) 

ファイルを1閉じていることを確認します。この方法では))は、常に

+0

ありがとうございます。あなたのソリューションは正常に動作します。私はStringsFilterクラスのログを複製していることに気づいていませんでした。また、おそらく私はおそらくファイルを正しく閉じていないので、現在withステートメントを使用してエラーが発生することはありません。ファイルが多すぎます。 – Libor

+0

@Libor私はうまく働いてうれしいです:)答えを受け入れることを考えて/ upvotingしてください。 – MateuszL

関連する問題