generators shared among threads

Kent Johnson kent at kentsjohnson.com
Wed Mar 8 12:05:26 CET 2006


Paul Rubin wrote:
> Hmm (untested, like above):
> 
>     class Synchronized:
>        def __init__(self, generator):
>           self.gen = generator
>           self.lock = threading.Lock()
>        def next(self):
>           self.lock.acquire()
>           try:
>              yield self.gen.next()
>           finally:
>              self.lock.release()
> 
>     synchronized_counter = Synchronized(itertools.count())
> 
> That isn't a general solution but can be convenient (if I didn't mess
> it up).  Maybe there's a more general recipe somewhere.

This code is not allowed in Python 2.4. From PEP 255:

Restriction:  A yield statement is not allowed in the try clause of a
try/finally construct.  The difficulty is that there's no guarantee
the generator will ever be resumed, hence no guarantee that the finally
block will ever get executed; that's too much a violation of finally's
purpose to bear.

Even if this was allowed, ISTM the semantics might be the same as your 
previous attempt - I would expect the finally to be executed after the 
yield returns, meaning the lock would be held during the yield.

Python 2.5 will allow this (see PEP 342) but from the examples it seems 
the finally won't execute until the yield returns.

Kent



More information about the Python-list mailing list