Ich habe die Eventlet-Operation als nicht blockierende E / A-Programmierung in Python ausprobiert. Es ist jedoch schwierig, von Grund auf neu zu schreiben, während Sie das Verhalten von Eventlet verstehen. Daher habe ich auf den Implementierungscode auf der OpenStack Nove_compute-Seite verwiesen. Live_migration auf der Nove_compute-Seite
Zunächst ein Beispielprogramm, das nur den benutzerseitigen Thread (grüner Thread) selbst betreibt. .. ..
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()
Versuche dich zu bewegen
$ python sample1.py
### Sample processing thread has started
.
..
...
....
### Sample processing thread has finished
Nehmen wir als nächstes an, Sie möchten mehrere grüne Threads betreiben, die Operationen verknüpfen und ein wenig erweitern. .. ..
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()
Ich versuchte mich zu bewegen
$ 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]
Mit einem schönen Gefühl kann ich nun beobachten, wie der Vorgang des grünen Fadens auf der Seite der Beispielverarbeitung abgeschlossen ist.
Wenn Sie den internen Mechanismus der [Eventlet-Ereignisklasse] überprüfen (https://github.com/eventlet/eventlet/blob/master/eventlet/event.py#L16-L67),
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)
Es ist geworden.
Wenn Sie in sample2.py zunächst nur die Ereignisklasse instanziiert haben, self._result = NOT_USED Die Instanzvariable bleibt erhalten als, aber wenn event.send () aufgerufen wird, self._result = None Änderungen an.
Schließlich scheint es, dass die Überwachungsseite (_sample_processing_monitor) den Abschluss des Vorgangs des grünen Threads auf der _sample_processing-Seite beurteilen kann, indem sie den Inhalt von self._result nachschlägt.
Recommended Posts