Confused about when to use try, except and finally

I’m reading up on try:, except: & finally:
I can see how these can work in code, I just wonder how programmers use them.

Are they part the final code or are they only used while coding to easier debug?

As far as I understand I can code more meaningful errors and not have the program to crash when they encounter a certain error.

Despite being super annoying I thought it’s beneficial for the system to crash so I’m able to eradicate any bugs?
If I know where the problem is why would I use a specific code that override the ‘Python immune system’?

Hello @ktrager

I dont know much about this myself.
But I found this which I think is a very good reason to use

try:
except:
and finally:

try:
    f = open("demofile.txt")
    f.write("Lorum Ipsum")
except:
    print("Something went wrong when writing to the file")
finally:
  f.close()

In this code snippet a text file is opened to be written into.
Regardless if this work or fail the text file is closed afterward.
In TutorialPoint I found an explanation about pop()
I hope this answer is any useful.

1 Like

Thanks @ulfen69

Seems that this is the most popular way way of describing it.
And I guess it’s used as part of the ‘real’ code and not just for debugging purpose.

Definitely real code. I always use a try/except block when there is user input as you have no idea what will be entered.

If it’s fails your logic, you don’t want a nasty programme crash, you want to handle the error. Combined with a nice custom exception message, you can prevent the programme crashing and instruct the user to try again with more specific inputs.

A classic test case here is using negative numbers into an integer field. They are usually accepted as valid but if you are expecting positives only, it’s the last think you need.

3 Likes

Hi @gpkesley that is very good use case, and completely makes sense.

Divide by zero is another corker. See Pythons built-in exception: ZeroDivisionError

1 Like

For exception handling you should do it any time you call something that throws exceptions. Problem is, it’s too hard to figure out whether something you call can throw an exception because that function can call another function that throws them. My general policy is I work like this:

  1. I get the code working without exception handling.
  2. I then read the API docs to see what kind of exceptions my code can throw, and I add try/catch for most of them.
  3. I then write tests that thrash the code to make any undocumented exceptions pop up and handle those.
  4. If something throws a ton of exceptions then I try to wrap it in a function that handles them all and produce 1 exception. Paypal’s API is a great example of this where it comes from Java and Java loved exceptions for nearly everything.

This is a long an annoying process. The main flaw in exceptions is that programmers don’t know the difference between:

  1. A negative but expected result, meaning it’s something that can happen with a high probability but is a negative result.
  2. An exceptional error result that is unexpected and is not very common.

Python’s dict API is a very good example of getting this wrong. When you type code like this:

people = {'Zed': 50, 'Frank': 30}
age = people['Alex']

In every programming language on the planet that 2nd line is not an exceptional occurrence. You don’t get a negative or null result from a dictionary once in a blue mooon, you get them all the time. In fact it’s how you ask if something is in the people dict. Another way to put it is something NOT being inside a dict is really common because data is small and you also have no way of knowing what’s inside.

Python people though think not finding a key in a dict is an exceptional occurrence that never happens, so they raise an exception. That caused a problem because now how do you find out if something is in there, or how do you attempt to get something and then if it doesn’t exist get the default? That’s why Python also has the inefficient code like:

if 'Alex' in people:
   age = people['Alex']

Or, has the function that basically does what every other language does:

age = people.get('Alex')

So, when you write your code, you should throw exceptions only on things that are rare and unexpected error results. Everything else is considered a return result that can fit into normal logic.

The purpose of finally then is to do any kind of cleanup you need no matter what happens. A good example is closing a file:

try:
   data = open('data.file')
   # do stuff with data file
except:
   # oop! something terrible
finally:
   data.close()

The finally block then will run no matter what happens. If your code goes to try and works, finally is still called. If you have an exception, finally is still called.

2 Likes

Thank you for this thorough explanation.
I’ll keep this in mind.

But you also cleared up that its not only hard for beginners to figure out if something throws an exception or not, and it’s basically something I’ll find out by stress testing the code.

1 Like