Handling all but one exception
Solution 1
The answer is to simply do a bare raise
:
try:
...
except NoChildException:
# optionally, do some stuff here and then ...
raise
except Exception:
# handling
This will re-raise the last thrown exception, with original stack trace intact (even if it's been handled!).
Solution 2
New to Python ... but is not this a viable answer? I use it and apparently works.... and is linear.
try:
something
except NoChildException:
assert True
except Exception:
# handling
E.g., I use this to get rid of (in certain situation useless) return exception FileExistsError from os.mkdir.
That is my code is:
try:
os.mkdir(dbFileDir, mode=0o700)
except FileExistsError:
assert True
and I simply accept as an abort to execution the fact that the dir is not somehow accessible.
Solution 3
I'd offer this as an improvement on the accepted answer.
try:
dosomestuff()
except MySpecialException:
ttype, value, traceback = sys.exc_info()
raise ttype, value, traceback
except Exception as e:
mse = convert_to_myspecialexception_with_local_context(e, context)
raise mse
This approach improves on the accepted answer by maintaining the original stacktrace when MySpecialException is caught, so when your top-level exception handler logs the exception you'll get a traceback that points to where the original exception was thrown.
Related videos on Youtube
Ivan Vulović
Updated on June 06, 2022Comments
-
Ivan Vulović almost 2 years
How to handle all but one exception?
try: something except <any Exception except for a NoChildException>: # handling
Something like this, except without destroying the original traceback:
try: something except NoChildException: raise NoChildException except Exception: # handling
-
Gareth Latty about 11 yearsSimple answer: Don't. It's really bad practice to catch all exceptions, as you will tend to catch ones you didn't mean to, obscuring errors. There are only a tiny number of legitimate cases for doing such a thing.
-
matth about 11 yearsYou seem to have answered your own question. Tell us why you are unsatisfied with what you have.
-
Gareth Latty about 11 years@Robᵩ Not quite, his example will make a new exception, not re-raise the old one.
-
Tom Ferguson over 9 years@Lattyware There is no problem with catching all exceptions - e.g. to add extra context then reraising. However, swallowing all exceptions (as this example does), is bad practice.
-
-
Ivan Vulović about 11 yearsi agree. but i get this: Fail: Your Patient.update method caught an exception of type ZeroDivisionError when it shouldn't have. You should never use bare
except
clauses in your code. Only catch raised NoChildExceptions. instead of this: Successfully ignored raised exception of type: ZeroDivisionError Successfully ignored raised exception of type: NameError Successfully ignored raised exception of type: AttributeError Successfully ignored raised exception of type: TypeError Successfully ignored raised exception of type: ValueError Successfully caught raised NoChildException Test Completed -
Gareth Latty about 11 years@IvanVulović So what you want is to only catch
NoChildException
s (which is the exact opposite of what you have asked), so just dotry: ... except NoChildException: ...
, no need for anything fancy. -
Reinderien over 9 yearsAlso: never
except e
/raise e
. That swallows the stack trace. -
wim about 6 yearsHmm, nah. If you don't expect any exception in the test, don't catch any. If you do expect it, use
with self.assertRaises
orwith pytest.raises
and assert outside the context manager. -
wim about 6 yearsThis worked in older versions of Python, but now it's a
SyntaxError
. -
coyot about 6 yearsYou are assuming pytest as the framework. Bad assumption.
-
wim about 6 yearsNo, I'm not.
self.assertRaises
is unittest (stdlib). And nosetests is now deprecated, pytest is probably the most common test framework. -
coyot about 6 yearsI think the folks at nose2.readthedocs.io/en/latest would be very surprised to hear of your claim of deprecation. Especially since Python doesn't deprecate third party libraries, which asks the question, "Deprecated by whom?" . Also, having not done a survey of Python developers, I would be very hesitant to claim which is the most popular, especially in mature products. And to go back to the original point of the test which you missed and which assertRaises doesn't solve, is to test whether handle_it() handles the exception correctly.
-
wim about 6 years1. I guess nose2 is a fork, because nose is really deprecated according to the nose authors. Latest commit was over 2 years ago. 2. For your original point, it just doesn't make sense - if
my_module.my_method()
doesn't handleIOError
, then it will blow up the stack until it gets caught by the test runner - which will fail the test - so there is no need to catch it andassert False
inside the test. The test runner already does that job for you. So, that's useless to write into the test manually. Get it? -
wim about 6 yearsFWIW, my point stands even for nose runner - there is
nose.tools.assert_raises
in the original andnose2.tools.such.helper.assertRaises
in the newer project you've mentioned.