Pure python implementacja greenlet API

Pakiet greenlet jest używany przez gevent i eventlet do asynchronicznego IO. Jest napisany jako rozszerzenie C i dlatego nie działa z Jython lub IronPython. Jeśli wydajność nie ma znaczenia, jakie jest najprostsze podejście do implementacji greenlet API w czystym Pythonie.

Prosty przykład:

def test1():
    print 12
    gr2.switch()
    print 34

def test2():
    print 56
    gr1.switch()
    print 78

gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch()

Powinny drukować 12, 56, 34 (a nie 78).

Author: Tristan, 2010-05-30

2 answers

Tego typu rzeczy można osiągnąć dzięki Ko-procedurom, które zostały wbudowane w standardową dystrybucję Pythona od wersji 2.5. Jeśli IronPython i co są w pełni zgodne ze wszystkimi funkcjami Pythona 2.5 (wierzę, że są), powinieneś być w stanie użyć tego idiomu.

Zobacz Ten post aby uzyskać więcej informacji o tym, jak można je wykorzystać:) szczególnie zainteresuje cię PDF gdzie autor buduje system używając tylko czystego Pythona, który zapewnia podobne możliwości albo stackless Python lub moduł Greenlet.

Możesz również poszukać Gogena lub kamelii dla pomysłów: oba projekty mają czyste implementacje Pythona coroutine, które możesz zaadoptować lub użyć jako odniesienia do własnej implementacji. Spójrz na tę stronę , aby delikatnie wprowadzić w cogen sposób robienia rzeczy.

Zauważ, że istnieją pewne różnice między implementacjami co-routine i greenletimplementacja. Wszystkie implementacje Pythona używają jakiegoś zewnętrznego harmonogramu, ale idea jest zasadniczo taka sama: zapewniają sposób na uruchamianie lekkich, współpracujących zadań bez konieczności uciekania się do wątków. Dodatkowo oba frameworki powiązane z powyższym są nastawione na asynchroniczne IO bardzo podobne do samego greenlet.

Oto przykład, który napisałeś, ale przepisałeś za pomocą cogen:

from cogen.core.coroutines import coroutine
from cogen.core.schedulers import Scheduler
from cogen.core import events

@coroutine
def test1():
    print 12
    yield events.AddCoro(test2)
    yield events.WaitForSignal(test1)
    print 34

@coroutine
def test2():
    print 56
    yield events.Signal(test1)
    yield events.WaitForSignal(test2)
    print 78

sched = Scheduler()
sched.add(test1)
sched.run()

>>> 12
>>> 56
>>> 34

Jest nieco bardziej wyrazista niż wersja greenlet (dla przykład używając WaitForSignal aby jawnie utworzyć punkt CV), ale powinieneś uzyskać ogólny pomysł.

Edit: właśnie potwierdziłem, że to działa przy użyciu jython

KidA% jython test.py 
12
56
34
 12
Author: jkp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-07 17:20:35

Nie jest możliwe zaimplementowanie greenleta w czystym Pythonie.

UPDATE:

  • udawanie greenlet API z wątkami może być rzeczywiście wykonalne, nawet jeśli całkowicie bezużyteczne dla wszystkich praktycznych celów
  • Generatory nie mogą być używane do tego celu, ponieważ zapisują tylko stan pojedynczej klatki. Greenlets zapisać cały stos. Oznacza to, że gevent może używać dowolnego protokołu zaimplementowanego na standardowym gnieździe (np. Moduły httplib i urllib2). Framework oparty na generatorze wymaga Generatory we wszystkich warstwach oprogramowania, więc httplib i tony innych pakietów są wyrzucane.
 10
Author: Denis Bilenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 08:58:19