Обратные вызовы генератора на Twisted deferred - PullRequest
0 голосов
/ 24 июня 2018

Я пытаюсь перескочить в цепочке обратных вызовов для Twisted deferred, используя обратные вызовы, которые возвращают генераторы.Рассмотрим следующий фрагмент:

from twisted.internet import defer

def callback_one(result):
    print('Callback one: got "{}", will raise ZeroDivisionError'.format(result))
    raise ZeroDivisionError
    # yield

def errback_two(failure):
    print('Errback two: handled "{}", recovering'.format(failure.type))
    return 'recovered'

def callback_three(result):
    print('Callback three: got "{}"'.format(result))
    return 'Final result'

if __name__ == '__main__':
    d = defer.Deferred()
    d.addCallback(callback_one)
    d.addErrback(errback_two)
    d.addCallback(callback_three)
    d.callback('First result')

Выход для этого:

Callback one: got "First result", will raise ZeroDivisionError
Errback two: handled "<class 'ZeroDivisionError'>", recovering
Callback three: got "recovered"

Однако, если yield не прокомментирован с callback_one, я получу только

Callback three: got "<generator object callback_one at 0x104603af0>"

Если я правильно понимаю, то, что происходит, это то, что первый обратный вызов возвращает генератор, который не обрабатывается, пока не станет слишком поздно, исключение не перехватывается и, следовательно, ошибка не вызывается.

Подводя итог,вопрос заключается в следующем: если обратный вызов возвращает генератор, как я могу вызвать исключение из него таким образом, чтобы оно перехватывало отложенный объект, чтобы сработала цепочка errback?

Я новичок в Twisted, так что, возможно,то, что я пытаюсь сделать, это плохая практика или даже невозможное / действительно трудное достижение, пожалуйста, дайте мне знать, если это так.Заранее спасибо!

1 Ответ

0 голосов
/ 24 июня 2018

Если я правильно понимаю, чтобы получить результаты, такие как результат, полученный при комментировании yield, вам нужно вызвать генератор.Для этого вы можете создать другую функцию, которая просто выполняет генератор и внести незначительные изменения в вашу основную функцию:

def exec_gen(gen):
    """
    Execute the generator
    """
    for x in gen:
        print(x)
# ...

if __name__ == '__main__':
    d = defer.maybeDeferred(exec_gen, callback_one('First result'))
    d.addErrback(errback_two)
    d.addCallback(callback_three)
...