Витая: как обернуть функцию, которая принимает обратный вызов? - PullRequest
0 голосов
/ 13 июня 2018

В последнее время я пытаюсь использовать витую среду для решения некоторых задач асинхронного программирования.Одна вещь, которую я не совсем понимаю, - это как обернуть функцию, которая принимает функцию обратного вызова, и сделать ее функцией, которая возвращает отложенный объект?

Например, если у меня есть функция, подобная приведенной ниже:

def registerCallbackForData(callback):
   pass # this is a function that I do not control, some library code

А теперь я использую его просто для регистрации обратного вызова.Но я хочу иметь возможность включить это в скрученную структуру, возвращая отложенный объект, возможно, и позже использовать реактор.run ().Это возможно?

Ответы [ 2 ]

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

defer.maybeDeferred обернет вызов функции блокировки для возврата отложенного.Если вы хотите, чтобы вызов был неблокирующим, вы можете вместо этого использовать threads.deferToThread .

. Вы можете увидеть разницу, переключившись, какой вызов закомментирован:

import time
from twisted.internet import reactor, defer, threads


def foo():
    print "going to sleep"
    time.sleep(1)
    print "woke up"
    return "a result"


def show_result_and_stop_reactor(result):
    print "got result: %s, stopping the reactor" % result
    reactor.stop()


print "making the deferred"
d = defer.maybeDeferred(foo)
# d = threads.deferToThread(foo)

print "adding the callback"
d.addCallback(show_result_and_stop_reactor)

print "running the reactor"
reactor.run()
0 голосов
/ 13 июня 2018
def convert_callback_to_deferred(f):
    def g():
        d = Deferred()
        d.addCallback(callback)
        f(d.callback)
        return d
    return g

from somelib import registerCallbackForData

getSomeDeferredForData = convert_callback_to_deferred(registerCallbackForData)

d = getSomeDeferredForData()
d.addCallback(...)
...

Однако имейте в виду, что Deferred может дать не более одного результата.Если registerCallbackForData(cb) приведет к тому, что cb будет вызван более одного раза, некуда отправлять данные 2-го и последующих вызовов.Только если у вас есть источник события самое большее один раз, имеет смысл преобразовать его в интерфейс Deferred.

...