
On Thu, Sep 30, 2021 at 07:41:47AM -0300, Soni L. wrote:
You misnderstand exception hygiene. It isn't about "do the least stuff in try blocks", but about "don't shadow unrelated exceptions into your public API".
I disagree with that. I don't think that "exception hygiene" is a common term in software development (at least googling doesn't find many examples of the term) so it is not like there is a canonical definition beyond "clean use of exceptions", which is going to be at least partly subjective. I think that doing the least amount of work necessary inside a try block is a large part of exception hygiene. Likewise catching the smallest subset of exceptions that you know how to meaningfully handle. Large try blocks with a bunch of stuff inside them is an obvious Code Smell in the sense that Joel Spolsky talks about: https://www.joelonsoftware.com/2005/05/11/making-wrong-code-look-wrong/ As soon as I see a big block of code inside a try block, it smells a bit fishy and I know that I need to think *really carefully* about the possibility that maybe it is catching too many exceptions. try: n = len(item) # followed by thirty more lines of code... except TypeError: print('item is not a sequence') fallback() I have to think really hard, am I *really sure* that none of those other thirty lines can raise TypeError, which will then be wrongly diagnosed and wrongly handled? That's a code smell. It's not a clean use of exceptions. It is dirty, not clean. It is *unhygienic*.
For example, generators don't allow you to manually raise StopIteration anymore: [...] This is a (limited) form of exception hygiene. Can we generalize it?
Sure. See the "exception guard" recipe I posted. If you go to the recipe, it links to some discussions.
This effectively means all generators *are* wrapped in a try/except, so your point about "too much stuff inside a try block" goes directly against accepted practice and even existing python features as they're implemented.
StopIteration is very special. It doesn't even inherit from Exception. It is used directly for flow control by the interpreter. (Which goes against accepted practice in other languages: https://softwareengineering.stackexchange.com/questions/189222/are-exception... One might ask, is Python doing it wrong, is everyone else doing it wrong, or are we asking the wrong questions? By I digress.) We might take the point of view that StopIteration is reserved for use by iterators, and that the interpreter reserves the use to treat *any* use of StopIteration in any other context as undefined behaviour, and that we ought to be grateful that the interpreter merely converts it to a RuntimeError instead of making demons fly out of your nose. http://catb.org/jargon/html/N/nasal-demons.html So I don't think we should be too gung-ho about generalising from StopIteration (a specific exception used by the interpreter for flow control) to arbitrary exceptions which represent error conditions. (More to follow.) -- Steve