J'ai essayé l'opération Eventlet en tant que programmation d'E / S non bloquante en Python. Cependant, il est difficile d'écrire à partir de zéro tout en comprenant le comportement d'Eventlet, j'ai donc fait référence au code d'implémentation du côté d'OpenStack Nove_compute. Live_migration côté Nove_compute
Tout d'abord, un exemple de programme qui exploite uniquement le thread côté utilisateur (thread vert) par lui-même. .. ..
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()
Essayez de bouger
$ python sample1.py
### Sample processing thread has started
.
..
...
....
### Sample processing thread has finished
Ensuite, supposons que vous souhaitiez exploiter plusieurs threads verts et lier les opérations, puis développer un peu. .. ..
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()
J'ai essayé de bouger
$ 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]
Avec une belle impression, je peux maintenant observer l'achèvement de l'opération du thread vert du côté _sample_processing.
Si vous vérifiez le mécanisme interne de Eventlet's Event class,
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)
Il est devenu.
Au début, dans sample2.py, si vous venez d'instancier la classe Event, self._result = NOT_USED La variable d'instance est conservée en tant que, mais lorsque event.send () est invoqué, self._result = None Modifications de.
Enfin, il semble que le côté surveillance (_sample_processing_monitor) puisse juger de l'achèvement de l'opération du thread vert du côté _sample_processing en recherchant le contenu de self._result.
Recommended Posts