Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

Tricia Cruz
Tricia Cruz
915 Points

I still don't understand how the program would know to print the "More than 1..." string

After going through some of the other questions here, I think I understand why we had to raise the ValueError in the function, but:

Referring to the "Raising Exceptions" lesson - I still don't understand how changing except ValueError: to except ValueError as err: and then adding that additional line with print, causes the "More than 1..." string to be printed?

How did the program know that the err is the raise ValueError("More than 1...") from the function?

2 Answers

Jeff Muday
MOD
Jeff Muday
Treehouse Moderator 28,720 Points

I see where the confusion is coming from. Let's break it down step by step.

When you raise an exception in Python using the raise keyword, you can provide a message that describes the error. This message gets stored in the exception object that is raised.

For instance, consider the following code:

def check_value(x):
    if x > 1:
        raise ValueError("More than 1...")

If the function check_value is called with a value greater than 1, the ValueError exception is raised with the message "More than 1...".

Now, let's look at how the exception is caught:

try:
    check_value(2)
except ValueError as err:
    print(err)

The try block will attempt to execute the code within it. If an exception is raised inside the try block, the code in the except block will be executed.

The syntax except ValueError as err: is a way to catch the raised ValueError exception and assign it to the variable err.

Since we raised the ValueError with the message "More than 1...", that message is stored in the err object. When we print the err object, it prints the message associated with the exception, which in this case is "More than 1...".

That took a bit of background, but now to answer your question:

It's because the raise ValueError("More than 1...") in the function creates a ValueError exception object with the message "More than 1...". When this exception is caught in the except block with the as err syntax, the exception object (with its message) is assigned to the variable err. Printing err displays the message.

Tricia Cruz
Tricia Cruz
915 Points

Okay that makes a lot more sense now, thank you so much! 😭

I have another question though (I'm sorry) - is it possible to use multiple raise keywords in a function? Like, what if I raise a SyntaxError and a ValueError. In the except block, would that look like:

try: 
    check_value(2)
except ValueError as err:
    print(err)
except SyntaxError as err:
    print(err)

Or am I completely missing the mark?

Jeff Muday
MOD
Jeff Muday
Treehouse Moderator 28,720 Points

You're on the right track!

You are showing good instincts as a programmer. This is kind of an intermediate concept so you are going a bit above the task asked of you

You discovered this--> A function can contain multiple raise statements for different exceptions, but only one exception will be raised at a time. Once an exception is raised, the function's execution is interrupted, and the control is transferred to the nearest enclosing try-except block (or, if there's no appropriate try-except block, the program terminates with an error message).

Here's a quick example to illustrate:

def check_value(x):
    if x < 0:
        raise ValueError("Value should not be negative")
    if x == 0:
        raise SyntaxError("Value should not be zero")

try:
    # I am slightly deviating from your example by using -2
    check_value(-2)
except ValueError as err:
    print(err)
except SyntaxError as err:
    print(err)

TLDR;

(note: it's not recommended to use SyntaxError exceptions in code as you might mask pesky syntax errors!)

In the above code, the check_value(x) function can raise either a ValueError or a SyntaxError. In the try-except block, each exception type is caught by its corresponding except block.

If you call check_value(-2), it will raise a ValueError, and the first except block will catch it. If you call check_value(0), it will raise a SyntaxError, and the second except block will catch it.

You found out that once an exception is raised, the function's execution stops, and the program looks for an except block to handle that exception. If that exception is caught and handled, the function doesn't resume its execution from where the exception was raised.

PS: I was told by a true Python guru that using the try-except block is a good practice, but it's not performant (meaning it's a bit slow). So you might want to use these carefully as they cause a slight bottleneck in code.

Tricia Cruz
Tricia Cruz
915 Points

Thank you so much for expounding on this! Makes me feel better about progressing the lesson now 🥲