destructors, exceptions and the lock guard paradigm
Gonçalo Rodrigues
op73418 at mail.telepac.pt
Wed Jun 18 10:09:09 EDT 2003
On 17 Jun 2003 19:25:29 -0700, moocat94122 at yahoo.com (Ron Samuel
Klatchko) wrote:
>I am trying to use the lock guard paradigm in Python. My first
>attempt was
>this:
>
>class guard:
> def __init__(self, lock):
> self.acquired = 0
> self.lock = lock
> self.lock.acquire()
> self.acquired = 1
>
> def __del__(self):
> print "releasing lock"
> self.release()
>
> def release(self):
> if self.acquired:
> self.lock.release()
> self.acquired = 1
>
>Intended to be used like this:
>
>class someclass:
> def __init__(self):
> self.lock = threading.Lock()
>
> def somefunc(self):
> g = guard(self.lock)
> # do some work while the lock is held
>
>The idea was that when somefunc exited, the reference count to g would
>drop to 0, the guard would be destructed which would release the lock.
> That way, I do not have to manually release the lock for every exit
>path.
>
>While it works for normal returns from the function, the lock is not
>released when an exception is thrown. From my research it looks to be
>due to how the last traceback is stored and continues to hold a
>reference to the guard object.
Exactly -- see below.
>
>Is there a way to get this to work under Python? I realize I can use
>try/finally block and put the call to Lock.release() there, I don't
>like that as much as the guard method.
>
You should not rely on __del__ to release external resources. In
CPython, __del__ is called as soon as its reference count drops to
zero, but that is an implementation detail -- it is not true in Jython
for example, where the garbage collector kicks in a non-deterministic
fashion.
Also, imagine that your object participates in a cycle (a not too
uncommon occurence)...
So, basically, I guess you are stuck with the common Python idiom --
explicit release of resources via try/finally blocks.
>samuel
HTH, with my best regards,
G. Rodrigues
More information about the Python-list
mailing list