2016-10-13 6 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 

내가 이해할 수와 함께 종료 될 때까지, 한 번 더 할 때마다 반복을 가진 것 같아 의 문장이 인스턴스가 생성 될 때마다 여러 번 호출되는 이유는 무엇입니까? 당신은 같은 일을 왜

+0

오류를 '가져 오기'주 'stringsfilter.py''라인 9시 defined'되지 않습니다. –

+0

죄송합니다. 이제 추가되었습니다. – Libor

답변

0

이유는 여러 번 기록 : main.get_module_logger("StringsFilter")가 호출 될 때마다 하나 로거에 여러 핸들러를 얻을 수 있도록, 당신은 logging.getLogger(name)에서 반환 된 같은 로거에 logger.addHandler(...)를 호출합니다. 더 나은 열려있는 파일에 대해서는 모듈 수준 로거에게

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

을, 나는 이유를 볼 수 있지만, find_strings_and_move()with open(filename) as f: 구문을 사용하여 고려하지 않는다.

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 닫혀 있는지 확인이 방법으로) 이동 2 전) 항상

+0

고맙습니다. 당신의 솔루션은 잘 작동합니다. StringsFilter 클래스에서 로깅을 복제하고 있다는 것을 알지 못했습니다. 또한 with 문을 사용하여 Error로 끝나지 않으므로 아마도 파일을 제대로 닫지 않았을 것입니다. 너무 많은 파일이 열려 있습니다. – Libor

+0

@Libor 나는 그것이 기뻤다 :) 다음/대답을 upvoting 받아 들일 것을 고려하십시오. – MateuszL