"ファイルを一行ずつ読み込んで処理する"という要件は、あちこちで需要がありそうなので、モデルを考えてみました。 Process、FileFinder、FileHandler、LineHandlerの4つのクラスで構成します。
Process
処理全体の流れを制御します。FileFinder、FileHandler、LineHandlerを注入することで、動作をカスタマイズできるようにします。
class Process(object): def __init__(self, finder, file_handler, line_handler): if not isinstance(finder, FileFinder): raise Exception('finder is not FileFinder') if not isinstance(file_handler, FileHandler): raise Exception('file_handler is not FileHandler') if not isinstance(line_handler, LineHandler): raise Exception('line_handler is not LineHandler') self._finder = finder self._file_handler = file_handler self._line_handler = line_handler def exec(self): files = self._finder.find_files() for f in files: logging.debug('processing...' + f) if not os.path.exists(f): logging.warn('file does not exist: ' + f) continue self._file_handler.before_file_open(f) with open(f, 'r') as h: line_no = 1 while True: line = self._file_handler.next_line(h) if line is None: break self._line_handler.handle_line(line, line_no, f) line_no += 1 self._file_handler.after_file_close(f)
FileFinder
処理の対象になるファイルを探します。
class FileFinder(object): def find_files(self): return [] class PyFileFinder(FileFinder): def find_files(self): return filter(lambda x: x.endswith('py'), os.listdir('.'))
FileHandler
ファイルを読み込んで"行"を返します。
class FileHandler(object): def before_file_open(self, file_path): pass def after_file_close(self, file_path): pass def next_line(self, f): l = f.readline() if not l: return None return l.rstrip()
LineHandler
FileHandlerが返した"行"を処理します。
class LineHandler(object): def handle_line(self, line, lineno, file_path): print('{}:{}:{}'.format(file_path, lineno, line))
まだまだプロトタイプレベルなので、これから育てていけたらいいと思う。
0 件のコメント:
コメントを投稿