如果在循环中出现异常:How to return the intermediate result before passing on the exception?

In case of an exception during a loop: How to return the intermediate result before passing on the exception?

def store(self) -> list:
    result = []
    for url in self.urls():
        if url.should_store():
            stored_url = self.func_that_can_throw_errors(url)
            if stored_url: result.append(stored_url)
    return result

前言:不是实际的方法名称。选择愚蠢的名字来强调

在循环过程中可能会出现错误。在那种情况下,我希望 store() 返回中间结果,并且仍然引发原始异常以在不同的地方处理。

做类似的事情

try:
    <accumulating results ... might break>
except Exception:
    return result
    raise

遗憾的是没有成功,因为通常不会达到 raise stmt(因此返回一个空列表)。

你们对如何丢失中间结果有什么建议吗?

提前致谢 - 干杯!

不是你想象的那样。您不能引发异常并 return 一个值。

所以我认为您要求的是解决方法。在那里,我看到了两种可能性:

  1. return一个Flag/Exception沿实际return值:

Return 标志:

except Exception:
    return result, False

其中 False 是表示出错的标志

Return 异常:

except Exception as e:
    return result, e
  1. 既然 store 是某些 class 的方法,您可以引发异常并通过第二次调用检索中间结果,如下所示:
def store(self):
    result = []
    try:
        # something
    except Exception:
        self.intermediary_result = result
        raise

def retrieve_intermediary(self):
    return self.intermediary_result

鉴于我对 Python 的有限了解,我能想到的最佳答案总是 return 一对,其中第一部分是结果,第二部分是结果该对是一个可选的异常值。

def store(self) -> list:
    '''
    TODO: Insert documentation here.

    If an error occurs during the operation, a partial list of results along with
    the exception value will be returned.

    :return A tuple of [list of results, exception]. The exception part may be None.
    '''

    result = []

    for url in self.urls():

        if url.should_store():
            try:
                stored_url = self.func_that_can_throw_errors(url)
            except Exception as e:
                return result, e

            if stored_url: result.append(stored_url)

    return result, None

就是说,正如您所提到的,如果您在代码中的多个位置进行了此调用,则必须小心地在所有相关位置进行更改,并可能更改处理方式。类型检查在那里可能会有帮助,尽管我对 Python 的类型提示的了解非常有限。

与此同时,我有想法只使用一个累加器,它似乎是 'quickest' 现在修复,在调用 store() 的项目中更改最少。 并不是所有地方都需要(中间)结果(假设它是可选的)。所以...

我想与您分享:

    def store(self, result_accu=None) -> list:
        if result_accu is None:
            result_accu = []
        for url in self.urls():
            if url.should_store():
                stored_url = self.func(url)
                if stored_url: result_accu.append(stored_url)
        return result_accu

仍然返回一个列表,但可以通过在 accu 列表上引用访问中间结果。 使参数成为可选参数可以让项目中的大多数语句保持原样,因为结果并不是到处都需要。

store() 更像是一种命令,其中大部分数据完整性工作已经在其中完成。结果暂时还不错。

但是你们也让我注意到无论如何要处理中间结果还有很多工作要做。谢谢! @attalos @MelvinWM