On Wed, Mar 21, 2012 at 1:34 PM, Chris Rebert <c...@rebertia.com> wrote: > > On Wed, Mar 21, 2012 at 12:30 PM, John Gordon <gor...@panix.com> wrote: > > I'm writing an application that interacts with ldap, and I'm looking > > for advice on how to handle the connection. Specifically, how to > > close the ldap connection when the application is done. > > > > I wrote a class to wrap an LDAP connection, similar to this: > > > > import ldap > > import ConfigParser > > > > class MyLDAPWrapper(object): > > > > def __init__(self): > > > > config = ConfigParser.SafeConfigParser() > > config.read('sample.conf') > > > > uri = config.get('LDAP', 'uri') > > user = config.get('LDAP', 'user') > > password = config.get('LDAP', 'password') > > > > self.ldapClient = ldap.initialize(uri) > > self.ldapClient.simple_bind_s(user, password) > > > > My question is this: what is the best way to ensure the ldap connection > > gets closed when it should? I could write an explicit close() method, > > but that seems a bit messy; there would end up being lots of calls to > > close() scattered around in my code (primarily inside exception handlers.) > > > > Or I could write a __del__ method: > > > > def __del__(self): > > self.ldapClient.unbind_s() > > > > This seems like a much cleaner solution, as I don't ever have to worry > > about closing the connection; it gets done automatically. > > Yes, but not necessarily in a timely manner. Since its uses reference > counting, CPython /just so happens/ to finalize > non-cyclically-referenced objects promptly when they go out of scope, > but Python-the-language makes no such guarantee, and indeed some of > the other Python implementations explicitly disclaim that there may be > a significant delay before finalization is performed. > > > I haven't ever used __del__ before. Are there any 'gotchas' I need to > > worry about? > > In addition to the aforementioned problem regarding portability to > other Python implementations, see also the Warning box under: > http://docs.python.org/reference/datamodel.html#object.__del__ > > I concur with J.'s context manager suggestion.
Personally, I would combine both methods (and maybe throw in a close option as well). The standard interface would be to use the with context, however in cases where that is not possible, an explicit close is useful, and just in-case that is forgotten or missed, the __del__ is there as a final backup. The main case that context managers fail is when you need to break the creation and teardown into separate methods, such as when writing a more complex context manager. As Chris Rebert pointed out, there is no guarantee as to when the __del__ method is called. CPython will generally call it immediately, however if there are reference cycles it may never call it: class O(object): def __del__(self): print 'del' a = O() b = O() a.obj = b b.obj = a del a del b # After this, all references should be gone. Netiher a nor b are accessable anymore, right? # Yet del was never printed. Maybe a full garbage collection will help? import gc gc.collect() # Nope... Also, if the object exists and an exception is thrown, the object may be held onto for extended periods of time, or may never get cleaned up. A quick example of this issue: >>> class O(object): ... def __del__(self): ... print 'del' ... >>> def F(): ... o = O() ... raise RuntimeError() ... >>> F() # o is not garbage collected as sys.exc_info holds a reference to it >>> still in the traceback object. RuntimeError Traceback (most recent call last): File "<stdin-inspect>", line 1, in <module> File "<stdin-inspect>", line 3, in F RuntimeError >>> raise ValueError() # When another exception got thrown, it will get cleaned >>> up.... del ValueError Traceback (most recent call last): File "<stdin-inspect>", line 1, in <module> ValueError In any case, it still makes a decent fall-back in case the user of your code fails to properly clean-up. It will cover many of the common cases, though you do need to be careful to never get into a reference cycle if you have __del__ methods, or you get memory leaks. > > > Cheers, > Chris > -- > http://mail.python.org/mailman/listinfo/python-list -- http://mail.python.org/mailman/listinfo/python-list