I found the following example of a Context Manager for a File object:
class File(object):
def __init__(self, file_name, method):
self.file_obj = open(file_name, method)
def __enter__(self):
return self.file_obj
def __exit__(self, type, value, traceback):
self.file_obj.close()
Here, the work done by the manager, that is actually opening the file, happens in the __init__ method. However, in the accompanying text, they suggest that the file opening should happen in the __enter__ call:
Let’s talk about what happens under-the-hood.
- The with statement stores the exit method of the File class.
- It calls the enter method of the File class.
- The enter method opens the file and returns it.
- The opened file handle is passed to opened_file.
- We write to the file using .write().
- The with statement calls the stored exit method.
- The exit method closes the file.
Which is the correct approach in general? It seems to be that the work undone by __exit__ should happen in __enter__, not __init__ since those are paired 1:1 by the context manager mechanism, but this example leaves me doubtful.