Как совместить callLater и addCallback? - PullRequest
10 голосов
/ 18 ноября 2011

Это так сломано, я надеюсь, ты милостив ко мне:

reactor.callLater(0, myFunction, parameter1).addCallback(reactor.stop)
reactor.run()

myFunction возвращает отложенное.

Надеюсь, понятно, что я хочу сделать:

  • как только реактор заработает, я хочу позвонить myFunction. Вот почему я использую 0 в качестве параметра задержки. Нет ли другого пути, кроме callLater? Выглядит смешно, чтобы передать это задержка 0.
  • Я хочу остановить реактор, как только myFunction завершит задание.

Проблемы, которые у меня есть до сих пор:

  • AttributeError: DelayedCall instance has no attribute 'addCallback'. Справедливо! Как поместить обратный вызов в цепочку обратных вызовов, начатую myFunction тогда?
  • exceptions.TypeError: stop() takes exactly 1 argument (2 given).

Для решения второй задачи мне пришлось определить специальную функцию:

def stopReactor(result):
    gd.log.info( 'Result: %s' % result)
    gd.log.info( 'Stopping reactor immediatelly' )
    reactor.stop()

И измените код на:

reactor.callLater(0, myFunction, parameter1).addCallback(stopReactor)
reactor.run()

(все еще не работает из-за проблемы callLater, но stopReactor теперь будет работать)

Неужели нет другого способа вызвать reactor.stop, кроме как путем определения дополнительной функции?

Ответы [ 4 ]

21 голосов
/ 18 ноября 2011

IReactorTime.callLater и Deferred смешаны вместе twisted.internet.task.deferLater.

from twisted.internet import reactor, task

d = task.deferLater(reactor, 0, myFunction, parameter1)
d.addCallback(lambda ignored: reactor.stop())
reactor.run()
1 голос
/ 18 ноября 2011

Я хочу остановить реактор, как только myFunction завершит задание.

Итак, создайте оболочку, которая выполняет работу myFunction, а затем останавливает реактор?

def wrapper(reactor, *args):
    myFunction(*args)
    reactor.stop()

reactor.callLater(0, wrapper, reactor, ...)
0 голосов
/ 15 марта 2013

Если вам нужно вызвать обратный вызов каким-либо действием, просто сделайте это (возможно, нет необходимости возвращать отложенный или что-то в этом роде).Просто чтобы уточнить вещи (используя чисто отложенные):

from twisted.internet import reactor, defer

# That will be our deferred to play with
# it has callback and errback methods
d = defer.Deferred()

def my_function(x):
    print 'function', x
    # need to trigger deferred upon function run?
    # Lets tell it to do so:
    d.callback(x)

# That's our callback to run after triggering `d`    
def d_callback(y):
    print 'callback ', y

# now let's bind that callback to be actually launched by `d`
d.addCallback(d_callback)

# now adding another callback just to stop reactor
# note lambda simply helps to agree number of arguments
d.addCallback(lambda data: reactor.stop())

# so we'll call `my_function` in 2 secs, then it runs
# then it triggers `d` to fire its callbacks
# then `d` actually detonates the whole chain of its added callbacks

reactor.callLater(2, my_function, 'asdf') # 'asdf' is some stupid param

# Here how it works
print 'Lets start!'
reactor.run()
print 'Done!'
0 голосов
/ 18 ноября 2011

Вам необходимо прикрепить обратный вызов к отложенному, которое возвращает myFunction, так как callLater не возвращает функцию.Нечто подобное может работать:

reactor.callLater(0, lambda: myFunction(parameter1).addCallback(lambda _: reactor.stop())

Но это не проверено.

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

def ignoringarg(f):
    return lambda _: f()

И затем выполнить:

reactor.callLater(0, lambda: myFunction(paramater1).addCallback(ignoringarg(reactor.stop)))

(Что было бы действительно правильно, так это определить __rshift__ (и аналог на месте) для класса Deferred, чтобы вы могли сделать: myFunction(parameter1) >> reactor.stop, когда вы хотите отказаться от аргумента, илиmyFunction(parameter1) >>= someotherfunc когда вы хотите распространить аргумент. Если вы считаете, что злоупотребление haskellish синтаксисом «аккуратно», в любом случае.)

...