I tried Eventlet operation as non-blocking I / O programming in Python. However, it is difficult to write from scratch while understanding the behavior of Eventlet, so I referred to the implementation code on the OpenStack Nove_compute side. Live_migration on the Nove_compute side
First, a sample program that only operates the user-side threads (green threads) independently. .. ..
sample1.py
import eventlet
import time
eventlet.monkey_patch()
def _sample_processing():
print("### Sample processing thread has started")
for count in range(5):
print("." *count)
time.sleep(0.5)
print("### Sample processing thread has finished")
def start_sample():
opthread = eventlet.spawn(_sample_processing)
opthread.wait()
if __name__ == '__main__':
start_sample()
Try to move
$ python sample1.py
### Sample processing thread has started
.
..
...
....
### Sample processing thread has finished
Next, assuming that you want to operate multiple green threads and link the operations, expand a little. .. ..
sample2.py
import eventlet
import time
eventlet.monkey_patch()
def _sample_processing():
print("### Sample processing thread has started")
for count in range(5):
print("." *count)
time.sleep(0.5)
print("### Sample processing thread has finished")
def start_sample():
opthread = eventlet.spawn(_sample_processing)
finish_event = eventlet.event.Event()
def thread_finished(thread, event):
print("### Sample processing thread notification")
event.send()
opthread.link(thread_finished, finish_event)
time.sleep(0)
_sample_processing_monitor(finish_event)
def _sample_processing_monitor(finish_event):
while True:
if not finish_event.ready():
print("+++ thread is still running!![{}]".format(finish_event._result))
else:
print("+++ thread is done!![{}]".format(finish_event._result))
break
time.sleep(1)
if __name__ == '__main__':
start_sample()
I tried to move
$ python sample2.py
### Sample processing thread has started
+++ thread is still running!![NOT_USED]
.
+++ thread is still running!![NOT_USED]
..
...
+++ thread is still running!![NOT_USED]
....
### Sample processing thread has finished
### Sample processing thread notification
+++ thread is done!![None]
With a nice feeling, I can now observe the completion of green thread operations on the _sample_processing side.
If you check the internal mechanism of Event class of Eventlet,
class Event(object):
...
_result = None
_exc = None
def __init__(self):
self._waiters = set()
self.reset()
def __str__(self):
params = (self.__class__.__name__, hex(id(self)),
self._result, self._exc, len(self._waiters))
return '<%s at %s result=%r _exc=%r _waiters[%d]>' % params
def reset(self):
assert self._result is not NOT_USED, 'Trying to re-reset() a fresh event.'
self._result = NOT_USED
self._exc = None
def ready(self):
return self._result is not NOT_USED
...
def send(self, result=None, exc=None):
assert self._result is NOT_USED, 'Trying to re-send() an already-triggered event.'
self._result = result
if exc is not None and not isinstance(exc, tuple):
exc = (exc, )
self._exc = exc
hub = hubs.get_hub()
for waiter in self._waiters:
hub.schedule_call_global(
0, self._do_send, self._result, self._exc, waiter)
It has become.
At first, in sample2.py, if you just instantiate the Event class, self._result = NOT_USED The instance variable is retained as, but then when event.send () is invoked, self._result = None Changes to.
Finally, by looking up the contents of self._result on the monitoring side (_sample_processing_monitor), it seems that it will be possible to determine the completion of the green thread operations on the _sample_processing side.
Recommended Posts