BlogsDope image BlogsDope

Context Manager in Python

Jan. 6, 2021 PYTHON 167

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  

  1. __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 .   
  2. __enter__: after init it will go to the entered function  
  3. __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.
Let's use this class to check if it works 
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 returned self.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.
If you want to confirm that the file is closed or not, you can write the below statement, which returns true if the file is closed.
print(f.closed)

Output:

True

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

We have used the context manager as class, now let's try doing it for function. Before creating a context manager as a function, you should have some knowledge about generators, yield and decorators. So I am assuming you know about these or you can read from here.
First, we need to import the contextmanager from contextlib library. So that we can use this contextmanager decorator to decorate our generator function.
Let's write our previous context manager as a generator now. 
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 the with 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



Liked the post?
Editor's Picks
0 COMMENT

Please login to view or add comment(s).