Dayson D
Dayson D

Reputation: 321

'raise' inside 'try' , when and how do I use 'raise'?

So here's the code:

def fancy_divide(list_of_numbers, index):
    try:
        try:
            raise Exception("0")
        finally:
            denom = list_of_numbers[index]
            for i in range(len(list_of_numbers)):
                list_of_numbers[i] /= denom
    except Exception as ex:
        print(ex)

If I call :

fancy_divide([0, 2, 4], 0)

why does it not print out '0' ?

and if I edit the code like this :

def fancy_divide(list_of_numbers, index):
    try:
        try:
            raise Exception("0")
        finally:
            denom = list_of_numbers[index]
            for i in range(len(list_of_numbers)):
                list_of_numbers[i] /= denom
    except Exception as ex:
        raise Exception("0")
        print(ex)

and then call the same thing, it prints:

Traceback (most recent call last):

  File "<ipython-input-16-c1b0ac98281c>", line 1, in <module>
    fancy_divide([0, 2, 4], 0)

  File "/Users/dsn/.spyder-py3/temp.py", line 10, in fancy_divide
    raise Exception("0")

Exception: 0

Why is that ? And what is the right way to / when should I use raise?

Upvotes: 0

Views: 227

Answers (2)

Lord Salforis
Lord Salforis

Reputation: 602

def fancy_divide(list_of_numbers, index):
    try:
        try:
            raise Exception("0")  # 1
        finally:
            denom = list_of_numbers[index]
            for i in range(len(list_of_numbers)):
            list_of_numbers[i] /= denom
    except Exception as ex:
        print(ex)  # 2

Notice the numbers

1.This thing executes first triggering the except block outside the 2nd try and disregards other block.

2.This will be triggered as there is an exception in the try block.

Use raise inside the except block to avoid complicated things.

I would rewrite your code as:

def fancy_divide(list_of_numbers, index):
    try:
        # Your fancy divide logic here
    except Exception as ex:
        raise Exception('Something went wrong: {exception}'.format(exception=ex))
    finally:
        # Don't need to

Upvotes: 1

ShadowRanger
ShadowRanger

Reputation: 155373

Your finally block is raising an exception itself, a divide-by-zero error (because your denominator is 0). If a finally block executes as an exception is bubbling, and raises an exception of its own, it either:

  1. On Python 2, replaces the existing exception
  2. On Python 3, it wraps the existing exception in the new exception (creating a chain of exceptions, where the outermost one is the one that is checked, but the inner exceptions exist for context)

Your other code prints the traceback because you don't catch the second exception you raise at all (and it bypasses your print).

I'd suggest reading the exception tutorial to understand more; your example code is so contrived/pointless it's impossible to say what misunderstandings you really have, and what is just to illustrate a specific behavior to support your question.

Upvotes: 1

Related Questions