纯python实现greenlet API

时间:2010-05-30 17:52:59

标签: python ironpython jython

greenlet包由gevent和eventlet用于异步IO。它被编写为C-extension,因此不适用于Jython或IronPython。如果性能无关紧要,那么在纯Python中实现greenlet API的最简单方法是什么。

一个简单的例子:

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

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

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

应该打印12,56,34(而不是78)。

2 个答案:

答案 0 :(得分:12)

这种事情可以通过自2.5版以来内置于标准Python发行版的协同例程来实现。如果IronPython和co完全符合所有Python 2.5功能(我相信它们都是),那么你应该可以使用这个习惯用法。

有关如何使用它们的详细信息,请参阅this post :)具体来说,您将对PDF感兴趣,其中作者构建系统只使用提供类似功能的纯Python。无堆栈Python或Greenlet模块。

您可能还想查看GogenKamelia的想法:这些项目都有纯python协同程序实现,您可以采用它们,也可以将它们用作您自己实现的参考。请查看this page,了解cogen做事方式的简要介绍。

请注意,此处的协同例程实现与greenlet实现之间存在一些差异。纯python实现都使用某种外部调度程序,但这个想法基本相同:它们为您提供了一种运行轻量级协作任务的方法,而无需求助于线程。此外,与上述链接的框架都面向异步IO,非常类似greenlet本身。

以下是您发布但使用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

它比greenlet版本更明确(例如使用WaitForSignal明确创建一个简历点),但你应该得到一般的想法。

编辑:我刚刚确认这可以使用jython

KidA% jython test.py 
12
56
34

答案 1 :(得分:10)

在纯Python中实现greenlet是不可能的。

<强>更新

  • 使用线程伪造greenlet API确实可行,即使对于所有实际目的完全无用
  • 生成器不能用于此,因为它们只保存单个帧的状态。 Greenlets保存整个堆栈。这意味着gevent可以使用在标准套接字之上实现的任何协议(例如httplib和urllib2模块)。基于生成器的框架需要在软件的所有层中生成生成器,因此将丢弃httplib和大量其他软件包。