2010-05-30 5 views
19

Le package greenlet est utilisé par gevent et eventlet pour les E/S asynchrones. Il est écrit comme une extension C et ne fonctionne donc pas avec Jython ou IronPython. Si les performances ne sont pas préoccupantes, quelle est l'approche la plus simple pour implémenter l'API greenlet en pure Python.Implémentation python pure de greenlet API

Un exemple simple:

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

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

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

doit imprimer les 12, 56, 34 (et non 78).

+0

IronPython et Jython fonctionner sur les machines virtuelles qui sont entièrement filetés et ont leur propre IO appelle async - ne vous utilisez ceux? – Mark

+0

En fin de compte oui, mais je pensais à écrire une version python pure avant d'ajouter les versions spécifiques à la machine virtuelle. Cette forme de contrôle de flux n'est pas complètement intuitive. – Tristan

+0

Selon un commentaire sur l'une des réponses, votre but ultime est d'utiliser 'eventlet' dans IronPython ou Jython. Cela ne fonctionnera pas - pas à cause du 'greenlet's, mais à cause de' libevent', une bibliothèque C que 'eventlet' termine et dépend de sa boucle d'événement et de son réacteur. Vous pourriez éventuellement réimplémenter toute l'API 'libevent' en plus d'une boucle d'événements .NET ou Java native (du moins si vous ne vous souciez pas de la performance, comme vous ne le dites pas), mais c'est beaucoup de travail. – abarnert

Répondre

12

Ce genre de chose peut être réalisé avec des routines qui ont été intégrées à la distribution Python standard depuis la version 2.5. Si IronPython et co sont entièrement compatibles avec toutes les fonctionnalités de Python 2.5 (je crois qu'ils le sont), vous devriez être capable d'utiliser cet idiome.

Voir this post pour plus d'informations sur la façon dont ils peuvent être utilisés :) Plus précisément, vous serez intéressé par le PDF où l'auteur construit un système en utilisant rien d'autre que pur Python qui fournit des fonctionnalités similaires soit stackless Python ou le module Greenlet . Vous pouvez également rechercher Gogen ou Kamelia pour des idées: ces projets ont tous les deux des implémentations de pure corpore python que vous pouvez adopter ou utiliser comme référence pour votre propre implémentation. Jetez un oeil à this page pour une introduction douce à la cogen façon de faire les choses.

Notez qu'il existe quelques différences entre les implémentations de co-routine ici et l'implémentation greenlet. Les implémentations python pures utilisent toutes un type de planificateur externe, mais l'idée est essentiellement la même: elles vous offrent un moyen d'exécuter des tâches légères et coopératives sans recourir à des threads. En outre, les deux cadres liés à ci-dessus sont orientés vers des E/S asynchrones très similaires à greenlet lui-même.

Voici l'exemple que vous avez publié, mais réécrites avec 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 

Il est un peu plus explicite que la version greenlet (par exemple en utilisant WaitForSignal pour créer explicitement un point de reprise), mais vous devriez obtenir l'idée générale.

modifier: Je confirme que cela fonctionne en utilisant Jython

KidA% jython test.py 
12 
56 
34 
+0

génial !! _ _ _ _ – mlvljr

+1

Ceci est un bon exemple, mais je suis vraiment intéressant en utilisant exactement l'API greenlet, sans les déclarations de rendement. Je voudrais activer eventlet, qui nécessite greenlet, sur Jython et IronPython. – Tristan

+0

@tristan: si vous voulez émuler quelque chose comme greenlet, vous devrez prendre ces idées et les mettre dans une API identique. Il devrait être possible de trouver quelque chose de proche. Je peux essayer et vous montrer quelque chose comme ça mais je pense que vous devez prendre ce qui a été montré et courir avec! Clairement greenlet lui-même n'est pas disponible, mais cela montre que les principes reportés et sont possibles à réutiliser. – jkp

10

Il n'est pas possible d'implémenter greenlet en pur Python.

MISE À JOUR:

  • trucage API Greenlet avec des fils pourrait être en effet faisable, même si complètement inutile à toutes fins pratiques
  • générateurs
  • ne peuvent pas être utilisés pour ce qu'ils économisent seulement l'état d'un seul Cadre. Les Greenlets sauvent la pile entière. Cela signifie que gevent peut utiliser n'importe quel protocole implémenté sur le socket standard (par exemple, les modules httplib et urllib2). Les frameworks basés sur des générateurs nécessitent des générateurs dans toutes les couches de votre logiciel, donc httplib et beaucoup d'autres paquets sont jetés.
+2

Je sais que c'est juste, mais pourriez-vous élaborer sur * pourquoi *? – Glyph

+4

Pas possible ou pas performant? Pouvons-nous truquer l'API greenlet avec des threads? – Tristan

+1

En fait, c'est un point intéressant. Peut-être pourrions-nous simuler l'API greenlet avec des threads. Cependant, ce n'est pas pratique, car dans ce cas, gevent et eventlet vous fourniront l'API que vous avez déjà (comme les sockets), seulement avec plus de frais généraux. –