Do you know how the washing machine works?
Ok. So what we do
- Start the machine
- Select the mode in which we want to wash our clothes
That's It
We did not have to wait to stop the machine, it would stop automatically. However, if it was not automatic, we need to stop it manually. It's not tough to stop the machine manually, But what if you got busy at work and forgot!!! What do you think will happen?
Let's not think about the condition of clothes!
The same happens in programming, assume that we want to write on a file so it goes like this
- Python
f = open('filename.txt', 'w')
f.write("I am Washing clothes hahahaha!!!")
f.close()
You can see in the above program we have opened a file to write and then we needed to manually close it but if like the washing machine we forgot to do it.
If the file stays open, it gets locked for other resources to use it, until the process closes it itself and when you open the file again you will not see the changes you made. So like the automatic washing machine, here the context manager does it all. In the above program, we can use the context manager called with
so that our file gets automatically closed.
with open('file_name.txt', 'w') as f:
f.write('I am going to close automatically hahahaha!!!')
The above code will open a file, write the data and then close it, if any error occurs while writing the data, even then it will close the file.
Let's look at what a context manager really is.
What is a Context Manager?
Context manager helps you allocate and release resources. It creates a temporary context for you and deletes it later, for example in a hotel when you check-in, the room gets yours, but temporarily and as soon as you check-out, housekeeping cleans it fully as if you never stayed there. A hotel manager is like the context manager in Python who sees your room allocation and check-out details to make the room available for another guest.
Context manager releases the resources so there is availability and no resource leakage, so that our system does not slow down or crash. The best example of a context manager is with
statement that we discussed above.
Context Manager as Class
class open_file():
def __init__(self, file_name, mode):
self.file_name = file_name
self.mode = mode
def __enter__(self):
self.file=open(self.file_name,self.mode)
return self.file
def __exit__(self, err_type, err_value, err_traceback):
self.file.close()
We created a context manager class that has three functions
__init__
: this will execute as soon as you create the object of class. It has two parameters filename and mode in which it is opened .__enter__
: after init it will go to the entered function__exit__
: as soon as we go out of the block this function will execute. It has three parameters which are used when we get any error and want to find details about it.
with open_file('file_name.txt', 'w') as f:
f.write('Context_Manager class is working')
- So what happens when we write
open_file('file_name.txt', 'w')
, it goes to__init__
method and sets the attribute. - Since we are using the
with
statement, it execute our__enter__
method, which opens the file and returns it. - So our f variable is set to have the return value from the
__enter__
method that is why f is the file object in our context manager because in__enter__
method we have returnedself.file
. - Now it will execute the statements we have written inside the block.
- So as soon as we get out of the block
with
calls the__exit__
method and execute it.
print(f.closed)
Output:
Now as we were writing on file we get an error so how the error will be handled? In the __exit__
method, we mentioned err_type
, err_value
and err_traceback
these are the parameters that the exit method will use to handle the error. If any error occurs in our program, it will return None
, therefore, with
statement will raise the exception.
If the exit method returns True
then the with
statement will not raise any exception as True means the error has been handled.
So, let's try to handle the error
class open_file():
def __init__(self, file_name, mode):
self.file_name = file_name
self.mode = mode
def __enter__(self):
self.file=open(self.file_name,self.mode)
return self.file
def __exit__(self, err_type, err_value, err_traceback):
print("Error has been handled") #optional
self.file.close()
return True
Context Manager as Generator
contextmanager
from contextlib
library.
So that we can use this contextmanager
decorator to decorate our generator function.from contextlib import contextmanager
@contextmanager
def open_file(file_name,mode):
f = open(file_name,mode)
try:
yield f
except Exception:
print("Error has been handled")
finally:
f.close()
with open_file('file_name.txt', 'w') as f:
f.write('Context_Manager class is working')
You can think and understand the code like this,
- The code before
yield
, is like your__enter__
method in class Yield
is the code inside thewith
block- The code after yield is like the
__exit__
method.
So if you will get any error, it will be handled by the except block and the file will get closed every time, doesn't matter if we get an error or not as the finally
block can execute with or without error.
Hope, you got the understanding of Context Manager