Question

Code:

import gevent
import time

def func(a, t):
  time.sleep(t)
  print "got here", a

gevent.spawn(func, 'a', 4)
gevent.spawn(func, 'b', 0).join()
time.sleep(3)
print "exit"

Output:

got here a
got here b
exit

Expectation:

I never join on the first greenlet, so I expect that it will never execute; or, given the long sleep(), it should complete after the second greenlet.

Context:

I would like to be able to fire off a "throwaway" greenlet that populates a cache which I never join on and I never want to block to wait for the result of.

Was it helpful?

Solution

This is because time.sleep() isn't gevent-aware, so when join() is called, the execution flow will be:

  1. gevent.spawn(a) — pushes a "spawn a" operation onto the event queue
  2. gevent.spawn(b) — pushes a "spawn b" operation onto the event queue
  3. .join() — causes the main thread to yield and next event in the event queue is executed (in this case, a)
  4. a executes time.sleep(4), blocking the entire process for 4 seconds (but thread a doesn't yield because time.sleep() isn't gevent-aware)
  5. a terminates and the next event in the event queue is executed (in this case, b)
  6. b executes and terminates, and the next event on the queue is executed (in this case, jumping back into the main thread, causing the .join() to return)

Use either gevent.monkey or gevent.sleep() to see this perform as you'd expect.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top