I'm aware of raise ... from None
and have read How can I more easily suppress previous exceptions when I raise my own exception in response?.
However, how can I achieve that same effect (of suppressing the "During handling of the above exception, another exception occurred" message) without having control over the code that is executed from the except clause? I thought that sys.exc_clear()
could be used for this, but that function doesn't exist in Python 3.
Why am I asking this? I have some simple caching code that looks like (simplified):
try:
value = cache_dict[key]
except KeyError:
value = some_api.get_the_value_via_web_service_call(key)
cache_dict[key] = value
When there's an exception in the API call, the output will be something like this:
Traceback (most recent call last):
File ..., line ..., in ...
KeyError: '...'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File ..., line ..., in ...
some_api.TheInterestingException: ...
This is misleading, as the original KeyError is not really an error at all. I could of course avoid the situation by changing the try/except (EAFP) into a test for the key's presence (LBYL) but that's not very Pythonic and less thread-friendly (not that the above is thread-safe as is, but that's beside the point).
It's unreasonable to expect all code in some_api to change their raise X
to raise X from None
(and it wouldn't even make sense in all cases). Is there a clean solution to avoid the unwanted exception chain in the error message?
(By the way, bonus question: the cache thing I used in the example is basically equivalent to cache_dict.setdefault(key, some_api.get_the_value_via_web_service_call(key))
, if only the second argument to setdefault could be a callable that would only be called when the value needs to be set. Isn't there a better / canonical way to do it?)