当我必须捕获可能在生成器中发生的异常时,如何使try块尽可能小?
典型情况如下:
for i in g():
process(i)
如果g()
可以引发我需要捕获的异常,第一种方法是:
try:
for i in g():
process(i)
except SomeException as e:
pass # handle exception ...
但如果SomeException
中出现process(i)
,这也会抓住try:
for i in g():
except SomeException as e:
pass # handle exception ...
process(i)
(这是我不想要的)。
是否有处理这种情况的标准方法?某种模式?
我正在寻找的是这样的:
{{1}}
(但这当然是句法废话。)
答案 0 :(得分:3)
您可以转换内部块中发生的异常:
class InnerException(Exception):
pass
try:
for i in g():
try:
process(i)
except Exception as ex:
raise InnerException(ex)
except InnerException as ex:
raise ex.args[0]
except SomeException as e:
pass # handle exception ...
另一个选择是编写一个包装g
的本地生成器:
def safe_g():
try:
for i in g():
yield i
except SomeException as e:
pass # handle exception ...
for i in safe_g():
process(i)
答案 1 :(得分:2)
这种直接的方法似乎是打开for
构造(这使得不可能仅仅在生成器中捕获异常,因为它的语法)到它的组件中。
gen = g()
while True:
try:
i = gen.next()
except StopIteration:
break
process(i)
现在我们可以将我们预期的异常添加到try
块:
gen = g()
while True:
try:
i = gen.next()
except StopIteration:
break
except SomeException as e:
pass # handle exception ...
break
process(i)
那(除了地狱之外的丑陋)有缺点吗?还有更多:有更好的解决方案吗?
(我不会接受我自己的答案,因为它很难看,但也许其他人喜欢并赞成它。)
答案 2 :(得分:1)
在您的生成器中引发一种不同类型的异常,您将能够区分它。
class GeneratorError(Exception):
pass
def g():
try:
yield <smth>
except:
raise GeneratorError
try:
for i in g():
process(i)
except GeneratorError:
pass # handle generator error
except SomeException as e:
pass # handle exception .
答案 3 :(得分:0)
我不知道,如果它有效。您可以将g()
评估为列表。我无法测试它,因为我没有一个抛出异常的迭代器。
try:
glist = list(g())
except SomeException as e:
pass # handle exception ...
for i in glist:
process(i)