Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set your subtitle preferences in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please refer to our video player troubleshooting guide for assistance.

Cleaning Up After Errors

This lesson shows how to use finally to execute sections of your code that should always run whether or not exceptions are encountered. You’ll also see how finally can be used to clean up after executing your code as well as how it can be used to re-raise exceptions.

00:00 Other times when you’re handling exceptions, you’ll need to do some cleanup after the fact, so we’re going to quickly just stub out a class that needs some cleanup to be done. We’re going to create a class called Connection,

00:13 and define its .__init__(). It takes a name.

00:21 It also provides a function called .closer(), which is just a stub and it prints 'connection closed'.

00:34 So, this particular object needs to have its connection closed whenever it’s created. So if we go ahead and create something here, we’re going to create an instance of .closer().

00:45 We’re going to have a connection here. It’s going to go Connection(), I’m going to pass a name, so we’re just going to pass my name here, 'Mahdi'.

00:53 And we’re going to have that. Now we’re going to artificially raise an error in a function called .send(). So we’re going to define a function called .send(), so we’re going to try to send something along the line here.

01:04 We’re going to send my name, in this case—some piece of data, 'Mahdi'. We’re going to define a .send() function here.

01:13 It’s simply going to be def send(), some data. And then we’re going to raise a RuntimeError here. And when .send() is called on this particular thing… I missed a colon there. When we call .send(), it’ll cause an exception to happen, which will put it into this block. This will be printed.

01:34 And therefore, when we want to clean up the connection, therefore close it, we need to provide a finally block where our code—regardless of the exception happening or not—it will be run.

01:46 So, you try something. So, let’s say you’re doing your work. Normally, you’d put the Connection.close(), .close() is probably a better name for that function.Connection.close() here, we will then continue our execution of our program.

02:02 What you should do in a case like this is you’re not sure if whether or not it’ll except, but when it does, you want to make sure that things that you would have normally called on exit are still called. And that’s where the finally block comes into play.

02:15 The finally block will be run regardless of exception or not. It is responsible for things like cleanup or re-raising errors. You re-raise errors usually when you’re dealing with a larger system, which has its own set of errors that are understood by its maintainers.

02:31 What you can do is catch all these generic ones that come in the standard library, which are ZeroDivisionError, RuntimeError—there’s a whole list.

02:37 I’ll put that in the screencast notes. But what those let you do is re-raise system-defined errors, which can then trigger a bunch of other things. You can also use the finally block to roll back transactions.

02:50 So let’s say you’re trying to write multiple saves in a particular thing, and all those saves need to happen together. If one of them fails, you can roll back all those saves.

02:59 That’s the type of thing that you’d put in a finally block. In this particular case, we want to make sure our connection is closed, so we run conn.close(). So we will create a Connection, we will try to send something along that Connection, a RuntimeError will occur, this will be printed, we will then finally run conn.close(), and then if we feel the need, we can then raise another type of exception which is a BaseException.

03:25 So, maybe you want to take a moment and guess to see what’s actually going to happen.

03:31 So, you saw that the RuntimeError occurred. You saw that we closed the connection that we needed to close, and then a BaseException was raised. Now in a larger system, this would then again be caught by some monitoring portion, either Sentry, which is an excellent tool for monitoring web applications, or another system that deals with exceptions that happen in an application.

03:58 Another cool thing to note is if you simply want to re-raise the error that brought you here, all you need to call is raise. This has to do with the system.

04:09 It keeps track of all the exceptions that were raised. If you simply want to re-raise the exception that brought you here, all you need to call is the raise command without any attributes, and you’ll see that it’ll raise the RuntimeError again.

Become a Member to join the conversation.