On 2017-06-23 00:29, Cameron Simpson wrote:
On 23Jun2017 06:55, Steven D'Aprano email@example.com wrote:
On Thu, Jun 22, 2017 at 10:30:57PM +0200, Sven R. Kunze wrote:
We usually teach our newbies to catch exceptions as narrowly as possible, i.e. MyModel.DoesNotExist instead of a plain Exception. This works out quite well for now but the number of examples continue to grow where it's not enough.
(1) Under what circumstances is it not enough?
I believe that he means that it isn't precise enough. In particular, "nested exceptions" to me, from his use cases, means exceptions thrown from within functions called at the top level. I want this control too sometimes.
try: foo(bah) except IndexError as e: ... infer that there is no bah ...
Of course, it is possible that bah existed and that foo() raised an IndexError of its own. One might intend some sane handling of a missing bah but instead silently conceal the IndexError from foo() by mishandling it as a missing bah.
Naturally one can rearrange this code to call foo() outside that try/except, but that degree of control often leads to quite fiddly looking code with the core flow obscured by many tiny try/excepts.
One can easily want, instead, some kind of "shallow except", which would catch exceptions only if they were directly raised from the surface code; such a construct would catch the IndexError from a missing bah in the example above, but _not_ catch an IndexError raised from deeper code such within the foo() function.
Something equivalent to:
try: foo(bah) except IndexError as e: if e.__traceback__ not directly from the try..except lines: raise ... infer that there is no bah ...
There doesn't seem to be a concise way to write that. It might not even be feasible at all, as one doesn't have a way to identify the line(s) within the try/except in a form that one can recognise in a traceback.
Increment a counter on every function call and record it on the exception, perhaps?
If the exception's call count == the current call count, it was raised in this function.