The file will be open in the 'with' block and closed after the 'with' block.
with file('filename.txt') as f: for line in f: print(f)
To implement a context manager you'll have to create a class that inherits from object with a '__enter__' and '__exit__' method:
class Context(object): def __enter__(self): """Enter context""" def __exit__(self): """Exit context"""
Note that the syntax 'with <context_manager> [as <target>]:' assigns a target variable. This is the returned value of the '__enter__' method.
In my case I wanted to be able to nest contexts and ensure that nested contexts were propagated to the root context. My first idea was to have a class attribute and assign that in the '__enter__' method and return that value (even in nested contexts). This was the result:
class Context(object): current = None def __enter__(self): """Enter context""" if not Context.current: Context.current = self return Context.current def __exit__(self): """Exit context""" Context.current = None
After a quick test I noticed a nested context set the current context as None upon exit (the third 'print' statement will print None):
with Context() as root: print(Context.current) with Context() as nested: print(Context.current) print(Context.current)
To prevent this I modified the '__exit__' method to check if the '__exit__' is called for the root context. The final result looks like this:
class Context(object): current = None def __enter__(self): """Enter context""" if not Context.current: Context.current = self return Context.current def __exit__(self): """Exit context""" if self is Context.current: Context.current = None
By using the 'is' comparison the context only gets closed when the '__exit__' method is called for the root context manager.
Geen opmerkingen:
Een reactie posten