Search code examples
pythonlistexceptionaccumulator

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

Preface: not actual method names. Silly names chosen to emphasize

During the loop errors may occur. In that case, I desire the intermediate result to be returned by store() and still raise the original exception for handling in a different place.

Doing something like

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

sadly doesn't do the trick, since trivially the raise stmt won't be reached (and thus an empty list get's returned).

Do you guys have recommendations on how not to lose the intermediate result?

Thanks a lot in advance - Cheers!


Solution

  • It is not possible as you imagine it. You can't raise an exception and return a value.

    So I think what you are asking for is a work around. There, I see two possibilities:

    1. return a Flag/Exception along the actual return value:

    Return flag:

    except Exception:
        return result, False
    

    where False is the Flag telling that something went wrong

    Return Exception:

    except Exception as e:
        return result, e
    
    1. Since it appears, that store is a method of some class, you could raise the exception and retrieve the intermediary result with a second call like so:
    def store(self):
        result = []
        try:
            # something
        except Exception:
            self.intermediary_result = result
            raise
    
    def retrieve_intermediary(self):
        return self.intermediary_result