如何改进文件处理生成器函数,确保文件正确关闭且避免代码重复?
解决生成器中文件未正确关闭的问题
针对你遇到的生成器未迭代完时文件无法关闭的问题,有两种简洁的改进方案:
方案一:利用finally块确保文件关闭
直接修改原代码,将文件关闭逻辑移到finally块中——不管生成器是正常迭代完成、中途抛出异常还是被提前终止,finally块都会执行,从而保证文件被正确关闭:
def gen_reader(file, lookups, stopwords): is_file = False try: if isinstance(file, str): file = open(file, 'r', encoding='UTF-8') is_file = True lookups = list(map(str.lower, lookups)) stop_words = list(map(str.lower, stopwords)) for line in file: original_line = line line = line.lower() if any(lookup in line for lookup in lookups) \ and not any(stop_word in line for stop_word in stop_words): yield original_line.strip() except FileNotFoundError: raise FileNotFoundError('File not found') finally: if is_file: file.close()
方案二:用上下文管理器封装文件处理逻辑
如果想让代码更清晰、职责分离,可以用contextlib.contextmanager写一个通用的文件处理上下文,把打开/关闭文件的逻辑抽离出来,避免重复代码:
from contextlib import contextmanager @contextmanager def get_file(file): is_file = False try: if isinstance(file, str): file = open(file, 'r', encoding='UTF-8') is_file = True yield file finally: if is_file: file.close() def gen_reader(file, lookups, stopwords): lookups = list(map(str.lower, lookups)) stop_words = list(map(str.lower, stopwords)) with get_file(file) as f: for line in f: original_line = line line = line.lower() if any(lookup in line for lookup in lookups) \ and not any(stop_word in line for stop_word in stop_words): yield original_line.strip()
这个方案中,get_file上下文会自动处理文件的打开和关闭:如果传入的是文件名,就打开并在结束后关闭;如果是已打开的文件对象,直接返回它且不会额外关闭。生成器只需专注于筛选行的业务逻辑,代码更易维护。
内容的提问来源于stack exchange,提问作者jadrezz
相关产品推荐
相关产品推荐

