尝试产出最终-我们是否引发了异常?

8

简述

在finally子句中,是否有可能发现是否存在未处理的异常?

背景

我想遍历项目并对它们进行一些相对昂贵的处理,这可能会中断并引发异常。因此,我想保存我的位置。 但是,保存状态也很昂贵 - 因此我不想每次都这样做,只有在代码中出现异常时才保存

我想象中的形式大致如下:

def get_things(my_iterator):
    for items in my_iterator:
        try:
            yield item
        finally:
            if something_went_wrong():  # magic oracle function for failure
                save_state(item)
        continue_normal_processing()

但我不知道这是否可行。值得注意的是,except Exception:没有引发任何异常,因为该异常不在此函数中。


1
你是指在生成器之外抛出异常吗?那么 try:/ finally: 不是正确的方法;这里没有需要尝试的内容。 - Martijn Pieters
2
yield 如何引发异常?如果在生成下一个项时发生异常,那不是循环已经引发了异常吗?另外,为什么不直接使用 except 而非 finally - tobias_k
到底是什么引发了异常?my_iterator是否是异常的来源? - Martijn Pieters
你应该将TD;DR部分作为第一句话发布,因为这是回答此问题的人所看到的简短描述。 - User
2个回答

6

看来我完全错误地理解了except的行为。

def f():
    for i in range(10):
        try:
            yield i
        except Exception:
            print "Nope, this broke"
            raise


for x in f():
    print x
    if x == 2:
        raise IndexError

返回值

0
1
2
Nope, this broke
Traceback (most recent call last):
...
IndexError

4
我没料到会出现这种行为。不错。 - User
3
下一个被困惑的人需要了解更多信息:在生成器进行垃圾回收期间,“Nope, this broke”会被打印出来。 - Daniel Stutzbach
说句实话,我刚在2.7.12上运行了这个代码示例,但我没有得到“不好意思,这个坏了”的打印输出。 - Skinner927
@DanielStutzbach - 请问您是说这种行为只会发生在 f()生成器 函数的情况下吗? - PeterByte
1
在Python 3.8中,如果没有处理,它会引发“IndexError”。 - dawid

1
这应该与你想要的类似:


class CatchingExceptionsIterator:
    def __init__(self, generator):
        self.generator = generator
        self.error = None
    def __enter__(self):
        return self
    def next(self):
        if self.error is None:
            return next(self.generator)
        else:
            error = self.error
            self.error = None
            return self.generator.throw(*error)
    __next__ = next
    def __exit__(self, ty, err, tb):
        if ty is not None:
            self.error = ty, err, tb
            return True
    def __iter__(self):
        return self


def f():
    for i in range(10):
        try:
            print("yield")
            yield i
            print("returnFomYield")
        except:
            import traceback
            traceback.print_exc()


c = CatchingExceptionsIterator(f())
for i in c:
    with c:
        print(i)
        if i == 5:
            nameerror

它必须被调整以适应确切的使用情况。
输出为:

yield
0
returnFomYield
yield
1
returnFomYield
yield
2
returnFomYield
yield
3
returnFomYield
yield
4
returnFomYield
yield
5
Traceback (most recent call last):
  File "withiteration.py", line 27, in f
    yield i
  File "withiteration.py", line 39, in <module>
    nameerror
NameError: name 'nameerror' is not defined
yield
6
returnFomYield
yield
7
returnFomYield
yield
8
returnFomYield
yield
9
returnFomYield

还有一个额外的 finally 子句也会被执行。

在 finally 子句中是否有可能找出是否存在未处理的异常?

为什么?您可以使用 except。请详细解释。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接