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

Разница между "выходом" Торнадо и "выходом из" асинчо в механизме?

В Tornado мы обычно записываем следующий код для вызова функции асинхронно:

class MainHandler(tornado.web.RequestHandler):

    @tornado.gen.coroutine
    def post(self):
        ...
        yield self.handleRequest(foo)
        ...

    @tornado.gen.coroutine
    def handleRequest(self, foo):
        ...

Но в asyncio (будет поставляться с Python 3.4, можно установить из pip для Python 3.3), мы используем yield from для достижения того же:

@asyncio.coroutine
def myPostHandler():
    ...
    yield from handleRequest(foo)
    ...


@asyncio.coroutine
def handleRequest(foo)
    ...

Увидев код, разница составляет yield и yield from. Однако предыдущий handleRequest(foo) возвращает объект tornado.concurrent.Future, последний возвращает объект generator.

Мой вопрос в том, в чем разница между двумя вещами в механизме? Как проходит контроль? И кто называет фактический handleRequest и получает возвращаемое значение?

Append: У меня есть базовые знания о генераторах Python и итераторах. Я хотел понять, что достигли Торнадо и Асинчио, используя их, и в чем разница между этими двумя механизмами.

4b9b3361

Ответ 1

Существует огромная разница между ними. yield from берет другой генератор и продолжает уступать от этого генератора (делегируя ответственность как бы). yield дает только одно значение.

Другими словами, yield from, в простейшем случае, можно заменить на:

for value in self.handleRequest(foo):
    yield value

Если вы заменили строку yield from <expression> на yield <expression>, вы вернете весь генератор вызывающему, а не значения, которые генерирует генератор.

Синтаксис yield from был введен только в Python 3.3, см. PEP 380: Синтаксис для делегирования в подгенератор. Tornado поддерживает версии Python 2.6, 2.7 и 3.2 в дополнение к Python 3.3, поэтому он не может полагаться на синтаксис yield from. asyncio, с другой стороны, будучи базовой библиотекой Python, добавленной в 3.4, может полностью полагаться на синтаксис делегирования генератора yield from.

В результате Tornado должен будет выполнить пост-обработку значений, полученных от генератора @tornado.gen.coroutine, чтобы обнаружить, что был получен объект tornado.concurrent.Future; обработка кода @asyncio.coroutine может быть намного проще. И действительно, метод Tornado Runner.run() выполняет явные проверки типов для обработки делегированных задач.