扭曲:如何包装一个回调函数?

时间:2018-06-13 08:28:34

标签: python twisted

我最近尝试使用扭曲的框架进行一些异步编程任务。我不太明白的一件事是如何包装一个带回调函数的函数并使它成为一个返回延迟对象的函数?

例如,如果我有如下函数:

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

现在我使用它的方式就是注册一个回调。但是我希望能够将它合并到扭曲的框架中,可能会返回一个延迟对象并稍后使用reactor.run()。这可能吗?

2 个答案:

答案 0 :(得分:2)

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被多次调用,那么第二次及以下调用的数据就无处可去。只有拥有最多一次的事件源才有意义将其转换为Deferred界面。

答案 1 :(得分:-1)

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()