Handling all but one exception

2019-03-14 12:03发布

问题:

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

回答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!).



回答2:

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.



回答3:

I found a context in which catching all errors but one is not a bad thing, namely unit testing.

If I have a method:

def my_method():
   try:
      something()
   except IOError, e:
      handle_it()

Then it could plausibly have a unit test that looks like:

def test_my_method():
   try:
      my_module.my_method()
   except IOError, e:
      print "shouldn't see this error message"
      assert False
   except Exception, e:
      print "some other error message"
      assert False
   assert True

Because you have now detected that my_method just threw an unexpected exception.