【发布时间】:2012-07-07 04:32:37
【问题描述】:
这是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 块中,但事实证明,这是行不通的。所以我必须将try-except 添加到parsefunc 本身,然后以某种方式将异常传递给消费者:
def parsefunc(stream):
while not eof(stream):
try:
rec = read_record()
yield rec
except Exception as e:
?????
我不太愿意这样做,因为
- 在不打算处理任何异常的函数中使用
try是没有意义的 - 我不清楚如何将异常传递给消费函数
- 会有很多格式和很多
parsefunc's,我不想用太多的帮助代码弄乱它们。
有没有人建议更好的架构?
Google 员工注意事项:除了最佳答案之外,请注意 senderle's 和 Jon's 的帖子 - 非常聪明和有见地的东西。
【问题讨论】:
-
讨论一个设计通常需要相当详细的系统知识,所以在这里似乎很难给出建议。我的第一个想法是取消
parsefunc(),并将read_record传递给read()。这样,可以在调用read_record()之后立即处理异常。 -
我同意@SvenMarnach - 我阅读它的方式可能过于复杂 - 即,
parsefunc()负责消费记录,但是 - 如何适当parsefunc()选择用于流的其余部分? -
@SvenMarnach:实际上,我在
parsefunc中描述为do some stuff的代码相当大,所以我不能简单地摆脱它。 -
@JonClements:调用
read的人都知道数据的格式,并决定使用哪个解析器。 -
@
eof定义在哪里?
标签: python exception-handling generator