On Sun, Dec 18, 2011 at 6:27 PM, Tim Delaney <timothy.c.dela...@gmail.com> wrote: > On 18 December 2011 19:52, RangerElf <gustavo.cord...@gmail.com> wrote: >> >> Which is why the original .acquire() ... .release() idiom was wrong, this >> would better express the intent: >> >> try: >> lock.acquire() >> shared_container.append(...) >> finally: >> lock.release() > > > No - this is very bad. The lock must be acquired outside the try: - > otherwise if an exception is thrown while acquiring, you will try to release > a lock that you have not acquired. > > Which again is why using with is a much better option - you can't make this > kind of mistake.
Well, not unless you make the same mistake in the context manager itself. from contextlib import contextmanager @contextmanager def bad_context_manager(lock): try: lock.acquire() yield finally: lock.release() class Lock(object): def __init__(self): self.is_locked = False def acquire(self): assert False def release(self): assert self.is_locked, "Tried to release lock without acquiring it" with bad_context_manager(Lock()): pass Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib64/python2.7/contextlib.py", line 17, in __enter__ return self.gen.next() File "<stdin>", line 7, in bad_context_manager File "<stdin>", line 7, in release AssertionError: Tried to release lock without acquiring it Perhaps a (small) reason to avoid the contextmanager decorator and implement __enter__ and __exit__ instead. -- http://mail.python.org/mailman/listinfo/python-list