Re: Best way to disconnect from ldap?

2012-04-05 Thread Michael Ströder
John Gordon wrote:
> class ldap.LDAPObject
> Instances of LDAPObject are returned by initialize() and open()
> (deprecated).  The connection is automatically unbound and closed
> when the LDAP object is deleted.
> 
> So, given that, do I need to do anything at all?

Hmm, maybe the author of this statement (have to check who) did not know about
the caveats with __del__() when this was written ages ago. IIRC first
python-ldap release was for Python 1.4 back in '98. See use of dealloc() in
Modules/LDAPObject.c.

So I'd recommend to use the modern with-statement to make sure
LDAPObject.unbind_s() is really called. Being old-fashioned I used
try-finally-blocks until now.

Ciao, Michael.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Best way to disconnect from ldap?

2012-04-05 Thread John Gordon
In  John Gordon  writes:

> 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()

Thanks everyone for your input.  I learned a lot!

However, I just ran across this bit of documentation on python-ldap.org:

class ldap.LDAPObject
Instances of LDAPObject are returned by initialize() and open()
(deprecated).  The connection is automatically unbound and closed
when the LDAP object is deleted.

So, given that, do I need to do anything at all?

-- 
John Gordon   A is for Amy, who fell down the stairs
gor...@panix.com  B is for Basil, assaulted by bears
-- Edward Gorey, "The Gashlycrumb Tinies"

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Best way to disconnect from ldap?

2012-03-22 Thread Tycho Andersen
On Thu, Mar 22, 2012 at 05:26:11PM +, Steven D'Aprano wrote:
> 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?

I don't, really. It's just natural to assume that __del__ is the
"opposite" of __init__, when it's really not (i.e. every object is
__init__ed, but not every object is destructed and thus __del__'d).
Novice programmers may make this assumption (indeed, many experienced
programmers do as well).

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

Yeah, C++ was the first language which has destructors that came to
mind. It's certainly not my favorite ;-)

\t
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Best way to disconnect from ldap?

2012-03-22 Thread Terry Reedy

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

--
http://mail.python.org/mailman/listinfo/python-list


Re: Best way to disconnect from ldap?

2012-03-22 Thread Tim Chase

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



--
http://mail.python.org/mailman/listinfo/python-list


Re: Best way to disconnect from ldap?

2012-03-22 Thread Steven D'Aprano
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  
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
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Best way to disconnect from ldap?

2012-03-22 Thread Tycho Andersen
On Thu, Mar 22, 2012 at 06:27:45AM -0700, Chris Rebert wrote:
> On Thu, Mar 22, 2012 at 6:14 AM, Tycho Andersen  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
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Best way to disconnect from ldap?

2012-03-22 Thread Chris Rebert
On Thu, Mar 22, 2012 at 6:14 AM, Tycho Andersen  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
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Best way to disconnect from ldap?

2012-03-22 Thread Tycho Andersen
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
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Best way to disconnect from ldap?

2012-03-21 Thread Tim Chase

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.


-tkc


--
http://mail.python.org/mailman/listinfo/python-list


Re: Best way to disconnect from ldap?

2012-03-21 Thread Chris Kaynor
On Wed, Mar 21, 2012 at 1:34 PM, Chris Rebert  wrote:
>
> On Wed, Mar 21, 2012 at 12:30 PM, 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:
> >
> >    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 "", line 1, in 
  File "", 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 "", line 1, in 
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


Re: Best way to disconnect from ldap?

2012-03-21 Thread Chris Rebert
On Wed, Mar 21, 2012 at 12:30 PM, 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:
>
>    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.

Cheers,
Chris
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Best way to disconnect from ldap?

2012-03-21 Thread J. Cliff Dyer
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 +, 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
> gor...@panix.com  B is for Basil, assaulted by bears
> -- Edward Gorey, "The Gashlycrumb Tinies"
> 


-- 
http://mail.python.org/mailman/listinfo/python-list


Best way to disconnect from ldap?

2012-03-21 Thread John Gordon
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
gor...@panix.com  B is for Basil, assaulted by bears
-- Edward Gorey, "The Gashlycrumb Tinies"

-- 
http://mail.python.org/mailman/listinfo/python-list