Often times when coding a python masterpiece, there are certain things that could go wrong when executing your masterfully designed code. Things such as files or directories that are missing, empty strings, variables that are supposed to be strings but are actually arrays at run-time.
These things are called exceptions in Python. This is what the try
keyword is for.
It allows execution of potentially breaking code that is nested in a comfortable block. This block will attempt to catch any of those nasty exceptions, and then execute code to either recover from the error, or notify the user of the breakage.
For example, this function would like to run:
[python]
def succeed(yn):
if yn:
return True
else:
raise Exception("I can't succeed!")
[/python]
But, as we can tell, it has the potential to raise an exception. When an exception is raised, and it's not in a try
block with the proper exception handling, it will stop the execution of the code.
If this code is run as:
[python]
>>> succeed(True)
True
[/python]
It will be fine and no one will know the difference.
But, if it's run as
[python]
>>> succeed(False)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in succeed
Exception: I can't succeed!
[/python]
We get this lovely message about the code not being able to succeed. Except that it's not that lovely. It's actually pretty ugly.
So what can we do?
That's where the try
block comes in!
So, to make our above code run-time friendly, we can do this:
[python]
from random import randint
def handle_exception(e):
print(e)
print('But I can be safe!')
try:
succeed(randint(False, True))
except Exception as e:
handle_exception(e)
[/python]
What did we just do? Well, randint
will choose a random integer between the two given inputs. In this case, False
is 0 and True
is 1. So the succeed
function will randomly raise an exception.
Now with the except part. We tell Python to execute handle_exception
only if the succeed
function raises an exception.
So if we run this code, the output will either be nothing, if we succeed, and if we don't:
[python]
I can't succeed!
But I can be safe!
[/python]
But what if you want to execute a piece of code after a success? You could do this
[python]
def another_method_that_could_fail():
fail = randint(False, True)
if fail:
raise RuntimeError('I definitely failed.')
else:
print("Yay! I didn't fail!")
try:
succeed(randint(False,True))
another_method_that_could_fail()
except Exception as e:
handle_exception(e)
[/python]
Now, we see that if succeed
doesn't raise an exception, then another_method_that_could_fail
runs! Amazing! We did it!
But wait! If another_method_that_could_fail
runs, it will run handle_exception
again, and we want to print a different message. Darn.
So what do we do? Well, we could add another piece to our try
block like so:
[python]
def handle_runtime(re):
pass
try:
succeed(randint(False, True))
another_method_that_could_fail()
except RuntimeError as re:
handle_runtime(re)
except Exception as e:
handle_exception(e)
[/python]
Okay, that's all well and good. But now, how do we run a piece of code on a successful run, with no exceptions? Well, there is a part of the try
block that is not well known. It's the the else
keyword. Observe:
If we take our previous code, and modify it a bit:
[python]
try:
succeed(randint(False, True))
another_method_that_could_fail()
except RuntimeError as re:
handle_runtime(re)
except Exception as e:
handle_exception(e)
else:
print('Yes! No exceptions this time!')
[/python]
Then we get a nice message printed only when we succeed. Okay, but what if we need a piece of code to run no matter what? Useful for, say, closing a file that has been opened in the try
block? Yes!
From stage left, enter the finally
keyword. It will do exactly what we want.
Observe it in glorious action:
[python]
try:
succeed(randint(False, True))
another_method_that_could_fail()
except RuntimeError as re:
handle_runtime(re)
except Exception as e:
handle_exception(e)
else:
print('Unknown error occurred. Exiting.')
exit(2)
finally:
print("Finally! I'm done. I don't care if I failed or not. I'm DONE.")
[/python]
And Voilà! There we have it. Now we will always print the message in the finally
section.
That's it for the try/except/else/finally block. I hope I educated you well in your quest to become a Python master.
Sayōnara, for now.