Чистая Python реализация API-интерфейса greenlet - PullRequest
20 голосов
/ 30 мая 2010

Пакет greenlet используется gevent и eventlet для асинхронного ввода-вывода. Он написан как расширение C и поэтому не работает с Jython или IronPython. Если производительность не имеет значения, какой самый простой подход к реализации greenlet API в чистом 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).

Ответы [ 2 ]

12 голосов
/ 07 июня 2010

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

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

Вы также можете поискать идеи либо: Gogen , либо Kamelia : оба эти проекта имеют чистые реализации сопрограмм Python, которые вы можете либо принять, либо использовать в качестве ссылки для собственной реализации , Взгляните на эту страницу , чтобы получить представление о том, как cogen делать что-то.

Обратите внимание, что здесь есть некоторые различия между реализациями подпрограммы и реализацией greenlet. Все реализации на чистом Python используют какой-то внешний планировщик, но идея по сути та же: они дают вам возможность выполнять легкие совместные задачи без необходимости прибегать к потокам. Кроме того, обе платформы, связанные с вышеупомянутыми, ориентированы на асинхронный ввод-вывод, очень похожий на 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
10 голосов
/ 31 мая 2010

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

UPDATE:

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