0

I'm creating a simple program that uses the eventlet greenthreads and I cannot understand their behavior. From the following example it seems to me that the thread only runs when I call the .wait() method. I read the documentation and I can't find any method similar to the "start" method provided by the threading module. Is there any similar method to force the thread to run just after creation (spawn call)?

Python 2.7.6 (default, Oct 26 2016, 20:30:19) 
[GCC 4.8.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import eventlet
>>> def test():
...     print("this is a test")
... 
>>> gth = eventlet.spawn(test)
>>> 
>>> gth.wait()
this is a test
>>> 
rkachach
  • 16,517
  • 6
  • 42
  • 66
  • The docs clearly say [this](http://eventlet.net/doc/modules/greenthread.html#eventlet.greenthread.GreenThread) about `spawn()`: `Execution control returns immediately to the caller; the created greenthread is merely scheduled to be run at the next available opportunity.` So, no, it's not being run because you're running it in the console, which _blocks_ until you yield control. Run it in a script instead, without `wait()`, and this snippet should work just fine. – Akshat Mahajan Jul 25 '17 at 17:50
  • I tried the same in a script and I got the same result :( .. it only runs when I call eventlet.sleep(0) – rkachach Jul 25 '17 at 17:51
  • Ah, I see. If you run it by itself, the main process would then exit before the green thread has a chance to run (damned if you do, damned if you don't :P) and thus all the information about the green thread would vanish. You can put the main thread to sleep, which is what you did. Aside from that, you don't have any other choices. – Akshat Mahajan Jul 25 '17 at 17:54
  • I still don't understand why the thread is not run immediately after the spawn specially when it doesn't any method to "start" it (such as the provided by the Thread class) – rkachach Jul 25 '17 at 17:55
  • The green thread itself is built on top of an internal scheduler that runs the green thread in the _same_ thread as your calling function. Calling `spawn()` simply places a request to schedule on that scheduler. Python does not feature pre-emption in any way or form - you can't interrupt a running thread unless it chooses to yield control, so this has to be done. You can always file an [issue](https://github.com/eventlet/eventlet/issues) with `eventlet` to find out more about this, or see if they have suggestions. You can also try [`greenpool`](http://eventlet.net/doc/modules/greenpool.html). – Akshat Mahajan Jul 25 '17 at 18:01
  • This [reference](https://stackoverflow.com/a/16641452/2271269) should explain why green threads don't feature pre-emptive multithreading. Everything is co-operative - hence you always need to yield control if you want another to run. Sadly, pre-emptive multitasking will always be hard because that's not in Python's hands, but rather determined by the kernel scheduler, and a pre-emptive thread in `threading` is subject to the GIL. – Akshat Mahajan Jul 25 '17 at 18:14
  • Okay, I see. Thank you very much for taking time to answer this. By now I'll just use the Thread from threading module which doesn't need explicit scheduling. – rkachach Jul 25 '17 at 20:09
  • Possible duplicate of [\`eventlet.spawn\` doesn't work as expected](https://stackoverflow.com/questions/14180179/eventlet-spawn-doesnt-work-as-expected) – temoto Jul 25 '17 at 22:12

1 Answers1

1

TL;DR: you need eventlet.sleep() or wait for something useful, usually network.

Observed behavior is expected for this synthetic test. Production code provides excessive opportunities for running other greenthreads. In other words: it actually works similar to OS threads with real code.

Eventlet provides cooperative multitasking. Every thread yields control to others, giving other threads chance to run. Eventlet can patch system libraries to yield when they usually block.

Please see https://stackoverflow.com/a/14227272/73957 for more verbose explanation.

temoto
  • 5,394
  • 3
  • 34
  • 50