Thread vs. generator problem

Robert Kern robert.kern at gmail.com
Fri May 26 18:49:13 EDT 2006


Paul Rubin wrote:
> As I understand it, generators are supposed to run til they hit a
> yield statement:
> 
>    import time
>    def f():
>      print 1
>      time.sleep(3)
>      for i in range(2,5):
>         yield i
> 
>    for k in f():
>       print k
> 
> prints "1" immediately, sleeps for 3 seconds, then prints 2, 3, and 4
> without pausing, as expected.  When I try to do it in a separate thread:
> 
>     import time, itertools
>     def remote_iterate(iterator, cachesize=5):
>         # run iterator in a separate thread and yield its values
>         q = Queue.Queue(cachesize)
>         def f():
>             print 'thread started'
>             for x in iterator:
>                 q.put(x)
>         threading.Thread(target=f).start()
>         while True:
>             yield q.get()
> 
>     g = remote_iterate(itertools.count)
>     print 'zzz...'
>     time.sleep(3)
>     print 'hi'
>     for i in range(5):
>         print g.next()
> 
> I'd expect to see 'thread started' immediately, then 'zzz...', then a 3
> second pause, then 'hi', then the numbers 0..4.  Instead, the thread
> doesn't start until the 3 second pause has ended.

My 10-second analysis is that *none* the body of a generator runs until a value
is requested from it.

In [3]: def f():
   ...:     print 'Starting f'
   ...:     for i in range(3):
   ...:         yield i
   ...:
   ...:

In [4]: g = f()

In [5]: for i in g:
   ...:     print i
   ...:
   ...:
Starting f
0
1
2

In your first example, you instantiate the generator and then iterate over it
immediately; in your second, you separate the two things. I don't think threads
have anything to do with it.

-- 
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
 that is made terrible by our own mad attempt to interpret it as though it had
 an underlying truth."
  -- Umberto Eco




More information about the Python-list mailing list