使用生成器读取文件时如何避免打印GeneratorExit异常信息
解决生成器忽略GeneratorExit的错误
这个问题的根源在于你用了裸except:语句,它会捕获包括GeneratorExit在内的所有异常——而这个异常是Python在生成器被强制关闭时(比如你的with块结束、文件被关闭,但生成器还没遍历完)自动抛出的,目的是让生成器正常清理并退出。当你捕获了它却不处理,Python就会抛出那个警告。
下面是几种修复方案,按推荐程度排序:
1. 精准捕获JSON解析异常(推荐)
只捕获json.loads()可能抛出的解析错误,不要用裸except。Python 3.5及以上版本可以直接捕获json.JSONDecodeError:
import json def json_generator(f): for line in f.read().splitlines(): try: yield json.loads(line) except json.JSONDecodeError: # 跳过解析失败的行 pass
如果是Python 3.4及更早版本,json.loads()解析失败会抛出ValueError,可以捕获这个类型:
import json def json_generator(f): for line in f.read().splitlines(): try: yield json.loads(line) except ValueError: pass
这样就不会捕获GeneratorExit,生成器可以正常响应关闭信号,不会再出现那个错误。
2. 手动处理GeneratorExit(不推荐,仅作参考)
如果你因为某些原因必须使用裸except,那需要在捕获后重新抛出GeneratorExit,让生成器正常退出:
import json def json_generator(f): try: for line in f.read().splitlines(): try: yield json.loads(line) except: pass except GeneratorExit: # 重新抛出异常,让生成器正常关闭 raise
不过这种写法不够优雅,也容易隐藏其他未知错误,所以优先推荐第一种方案。
额外优化:处理大文件更高效
你的代码里f.read().splitlines()会一次性把整个文件加载到内存,如果是超大JSON行文件,内存占用会很高。可以改成直接迭代文件对象,逐行读取,更节省内存:
import json def json_generator(f): for line in f: # 可选:去掉行首尾的空白和换行符 cleaned_line = line.strip() # 跳过空行 if not cleaned_line: continue try: yield json.loads(cleaned_line) except json.JSONDecodeError: pass
这样修改后,即使是几个G的大文件,也能流畅处理。
内容的提问来源于stack exchange,提问作者Carlos
相关产品推荐
相关产品推荐

