I am reading the Python Cookbook where the following is mentioned:
@contextmanager
is really only used for writing self-contained context-management functions. If you have some object (e.g. a file, network connection, or lock) that needs to support thewith
statement, you still need to implement the__enter
and__exit__
methods separately.
I can't quite understand this. Why can't we use a file object with a context-management function? Aren't functions decorated with @contextmanager
equivalent to classes with __enter__
and __exit__
methods?
Say you've got a class:
class DatabaseCursor(object):
...
and you want to add context manager functionality to it. Where would you put @contextmanager
?
Not here:
@contextmanager
class DatabaseCursor(object):
...
Not here:
class DatabaseCursor(object):
@contextmanager
def __init__(self, ...):
...
Not here:
class DatabaseCursor(object):
@contextmanager
def __enter__(self):
...
Nowhere, really. @contextmanager
doesn't help you add context manager functionality to existing classes. You can't even use @contextmanager
-decorated functions as base classes, because the implementation doesn't actually create a class. If you want your file-like object or database cursor or network connection or other closeable resource to support use as a context manager, you have to implement __enter__
and __exit__
directly.