Reputation: 415
Most likely I don't understand this fully but I have a class declared like
class db:
def __init__(self, name):
pass
#self._conn = get_conn(name)
def __enter__(self):
print('enter')
#self_conn.begin_transaction()
def __exit__(self, a, b, c):
print('exit')
#self._conn.commit()
def close(self):
print('close')
#self._conn.close()
When I use it like:
with db('bname') as db:
print('do something')
I get the expected output like:
enter
do something
exit
but when I use contextlib closing those functions don't get called at all
from contextlib import closing
with closing(db('bname')) as db:
print('do something')
I only get:
do something
close
My understanding was the contextlib closing can be used with context manager classes to call close
always but what am i missing?
Upvotes: 1
Views: 726
Reputation: 5037
The closing
class implements its own version of __exit__
. This calls close()
.
Since you're passing an instance of closing
to the with
block, the __exit__
method of the closing instance will get called and not yours.
Subclass the closing
class for your __exit__
to get called. Here's an example:
from contextlib import closing
class Db(closing):
def __init__(self):
super().__init__(self)
print('initializing')
def close(self):
print('closing')
def __enter__(self):
print('entering')
def __exit__(self, *exc_info):
print('exiting')
return super().__exit__(*exc_info)
with Db() as db:
print('running')
Output
initializing
entering
running
exiting
closing
Upvotes: 4
Reputation: 8064
It is the with
statement that executes the __enter__
and __exit__
blocks. In your second example, you are applying in on the closing
function, not on your db
class. That's why those methods don't get triggered.
Upvotes: 1