Подтвердить что ты не робот

Чистая реализация API-интерфейса greenlet на python

Пакет greenlet используется gevent и eventlet для асинхронного ввода-вывода. Он написан как C-расширение и поэтому не работает с Jython или IronPython. Если производительность не вызывает беспокойства, какой простой способ реализовать API-интерфейс greenlet в чистом Python.

Простой пример:

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).

4b9b3361

Ответ 1

Этот вид может быть достигнут с помощью совлокальных подпрограмм, которые были встроены в стандартный дистрибутив Python с версии 2.5. Если IronPython и co полностью совместимы со всеми функциями Python 2.5 (я считаю, что они), вы должны использовать эту идиому.

Смотрите этот пост для получения дополнительной информации о том, как их можно использовать:) В частности, вас будет интересовать PDF, где автор строит систему, используя только чистый Python, который предоставляет аналогичные возможности как без стекового Python, так и модуля Greenlet.

Вы также можете посмотреть Gogen или Kamelia для идей: эти проекты имеют чистые реализации python coroutine, которые вы могли бы использовать или использовать в качестве ссылки для своей собственной реализации. Взгляните на эту страницу за нежное введение в способ 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, чтобы явно создать точку возобновления), но вы должны получить общую идею.

edit: я только что подтвердил, что это работает с использованием jython

KidA% jython test.py 
12
56
34

Ответ 2

Невозможно реализовать greenlet в чистом Python.

UPDATE:

  • API-интерфейс API-интерфейса API с потоками может быть действительно выполнимым, даже если он абсолютно бесполезен для всех практических целей. Генераторы
  • не могут использоваться для этого, поскольку они сохраняют только состояние одного кадра. Greenlets сохраняют весь стек. Это означает, что gevent может использовать любой протокол, реализованный поверх стандартного сокета (например, модулей httplib и urllib2). Рамки на основе генератора требуют генераторов во всех слоях вашего программного обеспечения, поэтому httplib и тонны других пакетов выбрасываются.