这是 Handle an exception thrown in a generator 的后续事件并讨论一个更普遍的问题。
我有一个读取不同格式数据的函数。所有格式都是面向行或面向记录的,并且对于每种格式都有一个专用的解析功能,作为生成器实现。所以主读取函数得到一个输入和一个生成器,它从输入中读取其各自的格式并将记录传递回主函数:
def read(stream, parsefunc):
for record in parsefunc(stream):
do_stuff(record)
其中 parsefunc
类似于:
def parsefunc(stream):
while not eof(stream):
rec = read_record(stream)
do some stuff
yield rec
我面临的问题是,虽然 parsefunc
可以抛出异常(例如,从流中读取时),但它不知道如何处理它。负责处理异常的函数是主 read
函数。请注意,异常发生在每条记录的基础上,因此即使一条记录失败,生成器也应继续其工作并返回记录,直到整个流耗尽。
在上一个问题中,我尝试将 next(parsefunc)
放在 try
block 中,但事实证明,这是行不通的。所以我必须将 try-except
添加到 parsefunc
本身,然后以某种方式将异常传递给消费者:
def parsefunc(stream):
while not eof(stream):
try:
rec = read_record()
yield rec
except Exception as e:
?????
我不太愿意这样做,因为
- 在不打算处理任何异常的函数中使用
try
是没有意义的 - 我不清楚如何将异常传递给消费函数
- 会有很多格式和很多
parsefunc
的,我不想用太多的帮助代码弄乱它们。
有没有人建议更好的架构?
google人注意事项:除了置顶答案,关注senderle's和 Jon's帖子 - 非常聪明和有见地的东西。
最佳答案
你可以在 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
关于python - 在其消费者中处理生成器异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11366892/