suppressing exception context when it is not relevant

I'm aware of "raise ... from None" (from PEP 415). 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 anymore. Why would I want 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: ... But I find this 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). Also, yes, I could instead subclass dict and implement __missing__, but that's only a solution for this particular case. The problem (if you agree it's a problem) occurs any time an exception is not actually an error, but rather a condition that just happens to be indicated by an exception. 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? If not, would it make sense to re-introduce sys.exc_clear() for this purpose? (I originally asked about this here: http://stackoverflow. com/questions/30235516/how-to-suppress-displaying-the- parent-exception-the-cause-for-subsequent-excep but find the answer unappealing.) Vashek

On 11 October 2016 at 10:43, Václav Dvořák <vashek@gmail.com> wrote:
Yes, you can restructure the code so you're not doing further work in the exception handler, and instead do the work after the try/except block finishes and the exception context is cleared automatically: value = MISSING = object() try: value = cache_dict[key] except KeyError: pass if value is MISSING: value = some_api.get_the_value_via_web_service_call(key) cache_dict[key] = value (This is the general case of MRAB's answer, as the try/except KeyError/pass pattern above is what dict.get() implements) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On 11 October 2016 at 10:43, Václav Dvořák <vashek@gmail.com> wrote:
Yes, you can restructure the code so you're not doing further work in the exception handler, and instead do the work after the try/except block finishes and the exception context is cleared automatically: value = MISSING = object() try: value = cache_dict[key] except KeyError: pass if value is MISSING: value = some_api.get_the_value_via_web_service_call(key) cache_dict[key] = value (This is the general case of MRAB's answer, as the try/except KeyError/pass pattern above is what dict.get() implements) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
participants (3)
-
MRAB
-
Nick Coghlan
-
Václav Dvořák