Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Best way to disconnect from ldap?

Reply
Thread Tools

Best way to disconnect from ldap?

 
 
John Gordon
Guest
Posts: n/a
 
      03-21-2012
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.

I haven't ever used __del__ before. Are there any 'gotchas' I need to
worry about?

Thanks!

--
John Gordon A is for Amy, who fell down the stairs
http://www.velocityreviews.com/forums/(E-Mail Removed) B is for Basil, assaulted by bears
-- Edward Gorey, "The Gashlycrumb Tinies"

 
Reply With Quote
 
 
 
 
J. Cliff Dyer
Guest
Posts: n/a
 
      03-21-2012
Write a context manager.

Then you just do

with MyLDAPWrapper() as ldap
ldap.this()
ldap.that()

and when you leave the scope of the with statement, your ldap __exit__
method will get called regardless of how you left.

Cheers,
Cliff


On Wed, 2012-03-21 at 19:30 +0000, John Gordon 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:LDAP
>
> 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.
>
> I haven't ever used __del__ before. Are there any 'gotchas' I need to
> worry about?
>
> Thanks!
>
> --
> John Gordon A is for Amy, who fell down the stairs
> (E-Mail Removed) B is for Basil, assaulted by bears
> -- Edward Gorey, "The Gashlycrumb Tinies"
>



 
Reply With Quote
 
 
 
 
Chris Rebert
Guest
Posts: n/a
 
      03-21-2012
On Wed, Mar 21, 2012 at 12:30 PM, John Gordon <(E-Mail Removed)> 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/dat...object.__del__

I concur with J.'s context manager suggestion.

Cheers,
Chris
 
Reply With Quote
 
Chris Kaynor
Guest
Posts: n/a
 
      03-21-2012
On Wed, Mar 21, 2012 at 1:34 PM, Chris Rebert <(E-Mail Removed)> wrote:
>
> On Wed, Mar 21, 2012 at 12:30 PM, John Gordon <(E-Mail Removed)> 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/dat...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

 
Reply With Quote
 
Tycho Andersen
Guest
Posts: n/a
 
      03-22-2012
On Wed, Mar 21, 2012 at 04:49:54PM -0500, Tim Chase wrote:
> On 03/21/12 15:54, Chris Kaynor wrote:
> >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

>
> And more maddeningly, modules/objects used/called from within the
> __del__ may have already gone out of scope, producing
> head-scratching errors. I've been bitten by this enough times that
> I just stopped using __del__ completely.


I've had similar experiences. In fact, in light of all this - why does
__del__ exist at all? Novice python users may (reasonably) assume it
behaves similarly to a C++ destructor (even though the docs warn
otherwise).

Given that you can't trust __del__, is there a legitimate use case for
it?

\t
 
Reply With Quote
 
Chris Rebert
Guest
Posts: n/a
 
      03-22-2012
On Thu, Mar 22, 2012 at 6:14 AM, Tycho Andersen <(E-Mail Removed)> wrote:
> On Wed, Mar 21, 2012 at 04:49:54PM -0500, Tim Chase wrote:
>> On 03/21/12 15:54, Chris Kaynor wrote:
>> >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

>>
>> And more maddeningly, modules/objects used/called from within the
>> __del__ may have already gone out of scope, producing
>> head-scratching errors. ¬*I've been bitten by this enough times that
>> I just stopped using __del__ completely.

>
> I've had similar experiences. In fact, in light of all this - why does
> __del__ exist at all? Novice python users may (reasonably) assume it
> behaves similarly to a C++ destructor (even though the docs warn
> otherwise).
>
> Given that you can't trust __del__, is there a legitimate use case for
> it?


Writing resource classes (like `file`) in C? Their __del__()s
typically involve little/less Python-level stuff and thus less
paranoia need be exercised.
There is somewhat of a perverse incentive in having such last-ditch
clean-up mechanisms though. "This code seems to work fine without
`with`, so why bother changing it?"

Cheers,
Chris
 
Reply With Quote
 
Tycho Andersen
Guest
Posts: n/a
 
      03-22-2012
On Thu, Mar 22, 2012 at 06:27:45AM -0700, Chris Rebert wrote:
> On Thu, Mar 22, 2012 at 6:14 AM, Tycho Andersen <(E-Mail Removed)> wrote:
> > On Wed, Mar 21, 2012 at 04:49:54PM -0500, Tim Chase wrote:
> >> On 03/21/12 15:54, Chris Kaynor wrote:
> >> >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
> >>
> >> And more maddeningly, modules/objects used/called from within the
> >> __del__ may have already gone out of scope, producing
> >> head-scratching errors. *I've been bitten by this enough times that
> >> I just stopped using __del__ completely.

> >
> > I've had similar experiences. In fact, in light of all this - why does
> > __del__ exist at all? Novice python users may (reasonably) assume it
> > behaves similarly to a C++ destructor (even though the docs warn
> > otherwise).
> >
> > Given that you can't trust __del__, is there a legitimate use case for
> > it?

>
> Writing resource classes (like `file`) in C? Their __del__()s
> typically involve little/less Python-level stuff and thus less
> paranoia need be exercised.


Sure, but you still have no guarantee that __del__ will ever be
called, so it's a bad idea to rely on it to clean up anything.

> There is somewhat of a perverse incentive in having such last-ditch
> clean-up mechanisms though. "This code seems to work fine without
> `with`, so why bother changing it?"


Yeah, I guess I can see doing something like:
__del__ = __exit__
but anything beyond that seems risky...

\t
 
Reply With Quote
 
Steven D'Aprano
Guest
Posts: n/a
 
      03-22-2012
On Thu, 22 Mar 2012 08:14:47 -0500, Tycho Andersen wrote:

> I've had similar experiences. In fact, in light of all this - why does
> __del__ exist at all? Novice python users may (reasonably) assume it
> behaves similarly to a C++ destructor (even though the docs warn
> otherwise).


What makes you think that novice Python users will be familiar with C++
destructors?

Be careful about assuming that idioms in <INSERT FAVOURITE LANGUAGE HERE>
will be shared by all Python programmers, novice or expert.


> Given that you can't trust __del__, is there a legitimate use case for
> it?


I've never found the need to write one.



--
Steven
 
Reply With Quote
 
Tim Chase
Guest
Posts: n/a
 
      03-22-2012
On 03/22/12 12:26, Steven D'Aprano wrote:
> On Thu, 22 Mar 2012 08:14:47 -0500, Tycho Andersen wrote:
>> Given that you can't trust __del__, is there a legitimate
>> use case for it?

>
> I've never found the need to write one.


I've found the need to write them...then been frustrated by
things falling out of namespace reach, and found that context
managers do a much more reliable/understandable job, saving what
little sanity I had left.

So I'd say that __del__ was really only useful (for some sick,
sick definition of "useful") in versions of Python before
context-managers were readily available.

-tkc



 
Reply With Quote
 
Terry Reedy
Guest
Posts: n/a
 
      03-22-2012
On 3/22/2012 1:54 PM, Tim Chase wrote:
> On 03/22/12 12:26, Steven D'Aprano wrote:
>> On Thu, 22 Mar 2012 08:14:47 -0500, Tycho Andersen wrote:
>>> Given that you can't trust __del__, is there a legitimate
>>> use case for it?


It is part of original or early Python and pretty well superceded by
cyclic gc (which does not work for object with __del__ *because* of the
unreliability), explicit close methods, and now context managers.
>>
>> I've never found the need to write one.

>
> I've found the need to write them...then been frustrated by things
> falling out of namespace reach, and found that context managers do a
> much more reliable/understandable job, saving what little sanity I had
> left.


Which is one reason they were added .

> So I'd say that __del__ was really only useful (for some sick, sick
> definition of "useful") in versions of Python before context-managers
> were readily available.


And before cyclic gc, which does a better job of ordering deletions.

--
Terry Jan Reedy

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Best way to loop through ArrayList and remove elements on the way? Kevin Java 16 01-30-2008 08:54 PM
way way way OT: MCNGP Announcement Neil MCSE 174 04-17-2006 05:55 PM
Any way/Best way to simulate 3:2 mode on an S2 IS? Joe Digital Photography 0 03-09-2006 05:35 PM
AMD Opteron: 1-way, 2-way, ... Up to 8-way. John John Windows 64bit 12 12-27-2005 08:17 AM
What is the best way to make dual-way xml databinding? Stan ASP .Net 3 05-05-2005 02:07 PM



Advertisments