扭曲:检查是否已经调用了延迟

Cla*_*diu 2 python twisted deferred

这就是我正在努力实现的目标。我正在远程调用服务器以获取信息,我想阻止以等待信息。我创建了一个返回 Deferred 的函数,这样当 RPC 带着回复进来时,就会调用 deferred。然后我有一个从线程调用的函数threads.blockingCallFromThread(reactor, deferredfunc, args)

如果出现问题——例如,服务器出现故障——那么呼叫将永远不会解除阻塞。在这些情况下,我更喜欢延迟关闭,但有例外。

我部分成功了。我有一个延迟,onConnectionLost当连接丢失时它会消失。我将阻塞调用函数修改为:

    deferred = deferredfunc(args)
    self.onConnectionLost.addCallback(lambda _: deferred.errback(
        failure.Failure(Exception("connection lost while getting run"))))
    result = threads.blockingCallFromThread(
        reactor, lambda _: deferred, None)
    return result
Run Code Online (Sandbox Code Playgroud)

这工作正常。如果服务器宕机,则连接丢失,并触发 errback。但是,如果服务器没有关闭并且一切正常关闭,onConnectionLost仍然会被触发,并且这里的匿名回调尝试触发 errback,导致引发AlreadyCalled异常。

有没有什么巧妙的方法来检查延迟是否已经被解雇?我想避免将它包装在一个try/except块中,但如果这是唯一的方法,我总是可以求助于它。

Gly*_*yph 5

有办法,但你真的不应该这样做。触发 的代码Deferred应该跟踪它是否Deferred在关联状态下被触发。真的,当你触发 时Deferred,你应该忘记它,以便它可以被正确地垃圾收集;这样你就不必担心调用它两次,因为你不会再有对它的引用。

此外,看起来您是deferredfunc从您正在调用的同一个线程调用的blockingCallFromThread。不要那样做;返回的函数Deferreds最有可能调用反应器 API,而这些 API不是线程安全的。事实上,Deferred它本身并不是线程安全的。这就是为什么它是,而不是。你应该这样做。blockingCallFromThreadblockOnThisDeferredFromThreadblockingCallFromThread(reactor, deferredfunc, args)

如果你真的想要 errback-if-it's-been- called-otherwise-do-nothing 行为,你可能想要取消Deferred。