![](https://secure.gravatar.com/avatar/f3ba3ecffd20251d73749afbfa636786.jpg?s=120&d=mm&r=g)
On 12 June 2017 at 17:10, Serhiy Storchaka <storchaka@gmail.com> wrote:
Does it mean that we should rewrite every chunk of code similar to the above? And if such cumbersome code is necessary and become common, maybe it needs syntax support in the language? Or changing the semantic of exceptions raised in error handlers and finally blocks?
No, as in general there's no way for us to reliably tell the difference between intentionally changing the exception type (e.g. KeyError->AttributeError and vice-versa), unintentionally changing the exception type due to a bug in the cleanup code (e.g. SystemExit->KeyError), and the exception type changing due to external events (e.g. KeyError -> KeyboardInterrupt). So in the example given if an expected-and-allowed kind of exception can escape from "undo_something()", it's not really cleanup code, it's normal code, and needs to be refactored more like the way most close() methods work: particular known-to-be-possible exceptions get caught and reported (or silently ignored), but not propagated. That last example also shows that the suggested replacement idiom is incorrect, as it can suppress SystemExit, KeyboardInterrupt, etc. That said, as far as better builtin support for dynamic resource management goes: that would currently be contextlib.ExitStack. I'm also completely open to adding more hooks to let users tweak how that reports exceptions, including adding a contextlib.ResourceSet variant, which *doesn't* semantically nest the callback handling the way ExitStack does, and instead collects any exceptions raised into a new __cleanup_errors__ attribute on the original exception (thus leaving the original exception chain untouched). That would still need some fiddling to work out what to do in the "exception that doesn't inherit from Exception" case (probably clean up all the registered resources anyway then raise the first such exception caught, while still attaching all the others to __cleanup_errors__ on the original exception), but it's likely to be significantly more feasible than doing anything at the syntax level. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia