纯python实现greenlet API

Tri*_*tan 20 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()
Run Code Online (Sandbox Code Playgroud)

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

jkp*_*jkp 12

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

有关如何使用它们的更多信息,请参阅这篇文章 :)具体而言,您将对PDF中感兴趣,其中作者构建系统只使用纯Python,它提供与无堆栈Python或Greenlet模块类似的功能.

您可能还希望看看GogenKamelia的想法:这些项目都有纯python协程实现,您可以采用它们或将其用作您自己实现的参考.请查看此页面,了解对操作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
Run Code Online (Sandbox Code Playgroud)

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

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

KidA% jython test.py 
12
56
34
Run Code Online (Sandbox Code Playgroud)


Den*_*nko 10

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

更新:

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

  • 不可能或没有表现?我们可以用线程伪造greenlet API吗? (4认同)
  • 只有线程才能实现纯python版本.但我认为,为IronPython,Jython提供特定于VM的greenlet实现更有用 - 也许这有助于采用greenlet作为Python的标准模块. (3认同)
  • 我知道这是对的,但你能详细说明*为什么*? (2认同)