I saw this in someone's code. What does it mean?
def __enter__(self): return self def __exit__(self, type, value, tb): self.stream.close()
from __future__ import with_statement#for python2.5 class a(object): def __enter__(self): print 'sss' return 'sss111' def __exit__(self ,type, value, traceback): print 'ok' return False with a() as s: print s print s
Using these magic methods (
__exit__) allows you to implement objects which can be used easily with the
The idea is that it makes it easy to build code which needs some 'cleandown' code executed (think of it as a
try-finally block). Some more explanation here.
A useful example could be a database connection object (which then automagically closes the connection once the corresponding 'with'-statement goes out of scope):
class DatabaseConnection(object): def __enter__(self): # make a database connection and return it ... return self.dbconn def __exit__(self, exc_type, exc_val, exc_tb): # make sure the dbconnection gets closed self.dbconn.close() ...
As explained above, use this object with the
with statement (you may need to do
from __future__ import with_statement at the top of the file if you're on Python 2.5).
with DatabaseConnection() as mydbconn: # do stuff
PEP343 -- The 'with' statement' has a nice writeup as well.
If you know what context managers are then you need nothing more to understand
__exit__ magic methods. Lets see a very simple example.
In this example I am opening myfile.txt with help of open function. The try/finally block ensures that even if an unexpected exception occurs myfile.txt will be closed.
fp=open(r"C:\Users\SharpEl\Desktop\myfile.txt") try: for line in fp: print(line) finally: fp.close()
Now I am opening same file with with statement:
with open(r"C:\Users\SharpEl\Desktop\myfile.txt") as fp: for line in fp: print(line)
If you look at the code, I didn't close the file & there is no try/finally block. Because with statement automatically closes myfile.txt . You can even check it by calling
print(fp.closed) attribute -- which returns
This is because the file objects (fp in my example) returned by open function has two built-in methods
__exit__. It is also known as context manager.
__enter__ method is called at the start of with block and
__exit__ method is called at the end. Note: with statement only works with objects that support the context mamangement protocol i.e. they have
__exit__ methods. A class which implement both methods is known as context manager class.
Now lets define our own context manager class.
class Log: def __init__(self,filename): self.filename=filename self.fp=None def logging(self,text): self.fp.write(text+'\n') def __enter__(self): print("__enter__") self.fp=open(self.filename,"a+") return self def __exit__(self, exc_type, exc_val, exc_tb): print("__exit__") self.fp.close() with Log(r"C:\Users\SharpEl\Desktop\myfile.txt") as logfile: print("Main") logfile.logging("Test1") logfile.logging("Test2")
I hope now you have basic understanding of both
__exit__ magic methods.