这是处理生成器中引发的异常的后续操作,并讨论了一个更一般的问题。
我有一个功能,可以读取不同格式的数据。所有格式都是面向行或记录的,每种格式都有一个专用的解析功能,可以作为生成器来实现。因此,主读取函数获得一个输入和一个生成器,该生成器从输入中读取其各自的格式并将记录传递回主函数:
def read(stream, parsefunc): for record in parsefunc(stream): do_stuff(record)
哪里parsefunc是这样的:
parsefunc
def parsefunc(stream): while not eof(stream): rec = read_record(stream) do some stuff yield rec
我面临的问题是,尽管parsefunc可能引发异常(例如,从流中读取时),但它不知道如何处理它。负责处理异常的read功能是主要功能。请注意,异常是基于每个记录发生的,因此,即使一个记录失败,生成器也应继续其工作并产生记录,直到整个流耗尽为止。
read
在上一个问题中,我试图放next(parsefunc)一个try段落,但事实证明,这是行不通的。所以,我必须添加try- except到parsefunc自身,然后以某种方式提供例外的消费者:
next(parsefunc)
try
try- except
def parsefunc(stream): while not eof(stream): try: rec = read_record() yield rec except Exception as e: ?????
我不太愿意这样做,因为
有没有人建议更好的架构?
您可以在parsefunc中返回记录和异常的元组,并让使用者函数决定如何处理异常:
import random def get_record(line): num = random.randint(0, 3) if num == 3: raise Exception("3 means danger") return line def parsefunc(stream): for line in stream: try: rec = get_record(line) except Exception as e: yield (None, e) else: yield (rec, None) if __name__ == '__main__': with open('temp.txt') as f: for rec, e in parsefunc(f): if e: print "Got an exception %s" % e else: print "Got a record %s" % rec