This community-built FAQ covers the “Handling Exceptions II” exercise from the lesson “Context Managers”.
Paths and Courses
This exercise can be found in the following Codecademy content: Learn Intermediate Python3
FAQs on the exercise Handling Exceptions II
There are currently no frequently asked questions associated with this exercise – that’s where you come in! You can contribute to this section by offering your own questions, answers, or clarifications on this exercise. Ask or answer a question by clicking reply () below.
If you’ve had an “aha” moment about the concepts, formatting, syntax, or anything else with this exercise, consider sharing those insights! Teaching others and answering their questions is one of the best ways to learn and stay sharp.
Join the Discussion. Help a fellow learner on their journey.
Ask or answer a question about this exercise by clicking reply () below!
You can also find further discussion and get answers to your questions over in Language Help.
Agree with a comment or answer? Like () to up-vote the contribution!
If you want to match a type or any children of that type use isinstance instead of ==. The behaviour with isinstance/issubclass is similar to the behaviour of the except clause in a try statement where catching Exception catches any children of the Exception type too (which would be almost all runtime errors).
In many/most cases isinstance is used instead of type(obj) == because it allows types to replaced by a newer type that simply inherits from the old without breaking as much code (it handles inheritance which is normally considred good design). If you already have the type issubclass also handles inheritance.
As ever only catch the things you 100% want to catch so the most specific exception relevant to your problem and isinstance or issubclass would probably be the best way to go.
That’s a great answer. Thanks. But as good answers often do, it leads me to a new question. Why, then include the exc_type at all? Couldn’t we get that information from type(exc_value)?
Hmm, I think there’s a bit of a legacy issue with early versions of python when it comes to the three part value. In Python3 a single exception instance contains basically everything you need to know: type, value and traceback. The traceback for example is now bound to an exception too under .__traceback__. There are fewer tools that require all three parts but unfortunately they are still around, which I presume is because they can’t be removed without breaking too much legacy code.
You’d have to look into the history to find exactly why. I think trackbacks were a separate entity once upon a time (not bound in any way) and I think there was something funny about exception types being strings rather than real types which meant they were separate actions but that’s not something I know much about, if you’re really curious you might have to have a web search (it might go back to very early python versions).
Edit: Think I found the relevant details anyway:
The introduction of the .__traceback__ attribute: PEP 344 -- Exception Chaining and Embedded Tracebacks | Python.org
Note that some of the proposed future changes here (namely changing .__exit__ to a single parameter function never came about).
You are correct. I don’t know why the provided solution doesn’t include the additional close() method outside of the exception handler. I have to imagine that they were so focused on the exception handling that they forgot. We can verify the problem by trying to read the file outside of the context manager:
with PoemFiles('poem.txt', 'r') as file2:
print(file2.read())
print(" \n ---- Exception data below ---- \n ")
# this shouldn't work
file2.seek(0)
print(file2.read())
Outputs:
The moon is kind, warm and deep,
But she has promises to keep,
After cake and lots of sleep.
Sweet dreams come to her cheap.
As you’ve shown in your reply, we need to make sure to close the file when an exception is not raised:
This lesson has some issues. In the first codebox for example why does the exit method say self.file.close() instead of self.opened_file.close()? Seems like some Codecademy programmers should go practice the module on testing.
Aren’t we trying to see if the error type is an instance of an AttributeError? Why would the error value be an instance of an error type? I think I’m misunderstanding something…