简体   繁体   中英

In python 3.6, how do I catch an exception and raise an exception to be handled later?

Suppose I have 2 exceptions:

class FooError (Exception):
    def __init__(self, *args, **kwargs):
        default_message = 'A foo error has occurred!'
        if not (args or kwargs): args = (default_message,)
        super().__init__(*args, **kwargs)
class BarError (Exception):
    def __init__(self, *args, **kwargs):
        default_message = 'A bar error has occurred!'
        if not (args or kwargs): args = (default_message,)
        super().__init__(*args, **kwargs)

And, I have a function which throws FooError :

def foobar (x):
    if x < 0:
        raise FooError()

Generally, you would handle FooError with a try/except block:

try:
    foobar(-1)
except FooError:
    print('Uh oh, foo error!')
    sys.exit()

However, I would like to throw a BarError which I can handle later. Something like this:

except BarError:
    print('Uh oh, bar error!')
    sys.exit()

When executing this, though, I just get the traceback of both errors:

Traceback (most recent call last):
  File "C:\Users\Maze\Desktop\test2.py", line 17, in <module>
    foobar(-1)
  File "C:\Users\Maze\Desktop\test2.py", line 15, in foobar
    raise FooError()
__main__.FooError: A foo error has occurred!

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Maze\Desktop\test2.py", line 19, in <module>
    raise BarError()
__main__.BarError: A bar error has occurred!

How do I throw BarError inside of the handler for FooError , and then handle BarError in a different except block?

Not sure whether I understood what you were asking, but you can easily raise new exceptions in other exception handlers:

def call_foobar():
    try:
        foobar(-1)
    except FooError:
        print('Uh oh, foo error!')
        raise BarError()

try:
    call_foobar()
except BarError as e:
    print("Bar Error")

You don't necessarily need a function for this, nesting two try blocks would be possible as well.

Does this answer your question?

You can't. Once you've caught an exception, you can't transfer control to another except block in the same try statement. You can use a nested statement:

try:
    try:
        foobar(-1)
    except FooError:
        raise BarError
except BarError:
    print('Uh oh, bar error!')
    sys.exit()

Some additional work is necessary if you want to distinguish between BarError s raised directly by foobar and the BarError raised as a result of the FooError being caught. You can use exception chaining for this. See PEP-3134 for more details; this example may not be the best way to write this.

try:
    try:
        foobar(-1)
    except FooError as exc:
        raise BarError from exc
except BarError as exc:
    if isinstance(exc.__cause__, FooError):
        print("Caught a Foo-induced BarError")
    else:
        print("Caught a regular BarError")

It sounds like you want to catch a FooError or BarError , but you want to do a little extra work first if it is a FooError . If that's the case, you can catch both kinds of exception and only do the work for a FooError :

try:
    foobar(-1)
except (FooError, BarError) as e:
    if isinstance(e, FooError):
        # do extra work
    # Handle errors

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM