#python #python-3.4
#python #python-3.4
Вопрос:
У меня большое количество файлов, и мне нужно просмотреть их и выполнить поиск некоторых строк, когда строка найдена, файл копируется в новую папку, в противном случае он закрывается.
Вот пример кода:
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
И это продолжается, кажется, что с каждой итерацией каждый оператор из init выполняется еще раз, пока не будет открыто слишком много файлов и программа не завершится
OSError: [Errno 24] Too many files open
Я не могу понять, почему инструкции из init вызываются несколько раз при каждом создании экземпляра.
Комментарии:
1. Получение ошибки
'main' is not defined
в строке 9stringsfilter.py
.2. Извините, забыл о main.py . Это добавлено сейчас.
Ответ №1:
Причина, по которой одно и то же регистрируется несколько раз: при каждом main.get_module_logger("StringsFilter")
вызове вы вызываете logger.addHandler(...)
один и тот же регистратор, возвращаемый из logging.getLogger(name)
, поэтому вы получаете несколько обработчиков в одном регистраторе. Лучше создать регистратор на уровне модуля
import ...
LOG = main.get_module_logger("StringsFilter")
class StringsFilter:...
Что касается открытых файлов, я не вижу причины, но рассмотрите возможность использования with open(filename) as f:
синтаксиса в find_strings_and_move()
.
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) всегда
Комментарии:
1. Спасибо. Ваше решение работает нормально. Я не понимал, что дублирую ведение журнала в классе StringsFilter. Кроме того, я, вероятно, неправильно закрыл файлы, так как теперь использование инструкции with не приводит к ошибке: открыто слишком много файлов.
2. @Libor Я рад, что это сработало 🙂 Пожалуйста, подумайте о том, чтобы принять / поддержать ответ.