【问题标题】:how to call a callback function after certain amount of time如何在一定时间后调用回调函数
【发布时间】:2016-09-23 21:20:19
【问题描述】:

我正在使用 Twisted 和 Txmongo 库。 在以下函数中,我想在 5 秒后调用 cancelTest()。但是代码不起作用。我怎样才能让它发挥作用?

from twisted.internet import task

def diverge(self, d):
    if d == 'Wait':
        self.flag = 1
        # self.timeInit = time.time()
        clock = task.Clock()
        for ip in self.ips:
            if self.factory.dictQueue.get(ip) is not None:
                self.factory.dictQueue[ip].append(self)
            else:
                self.factory.dictQueue[ip] = deque([self])
                # self.factory.dictQueue[ip].append(self)

        log.msg("-----------------the queue after wait")
        log.msg(self.factory.dictQueue)
###############################HERE, this does not work
        self.dtime = task.deferLater(clock, 5, self.printData)
#############################
        self.dtime.addCallback(self.cancelTest)
        self.dtime.addErrback(log.err)
    else:
        self.cancelTimeOut()
        d.addCallback(self.dispatch)
        d.addErrback(log.err)



def sendBackIP(self):
    self.ips.pop(0)
    log.msg("the IPs: %s" % self.ips)

    d = self.factory.service.checkResource(self.ips)

    d.addCallback(self.diverge) ###invoke above function
    log.msg("the result from checkResource: ")
    log.msg()

【问题讨论】:

    标签: python twisted


    【解决方案1】:

    一般reactor.callLater()是你想要的功能。因此,如果需要在 5 秒后调用该函数,您的代码将如下所示:

    from twisted.internet import reactor
    reactor.callLater(5, cancelTest)
    

    奇怪的是,您的task.deferLater 实现也应该可以工作。但是,如果没有看到您的更多代码,我认为除了说明它很奇怪之外,我无法为您提供更多帮助:)

    参考文献

    【讨论】:

    • 一点也不奇怪 :-) Clock() 是 IReactorTime 的确定性模拟实现,因此除非调用 clock.advance(5),否则时钟永远不会移动。
    【解决方案2】:

    你几乎做对了所有事情;您只是没有正确获取时钟部分。

    twisted.internet.task.Clock 是 IReactorTime 的确定性实现,主要用于单元/集成测试,以从代码中获取确定性输出;你不应该在生产中使用它。

    那么,你应该在生产中使用什么? 反应堆!事实上,所有生产反应器的实现都实现了 IReactorTime 接口。

    只需使用以下导入和函数调用:

    from twisted.internet import reactor
    # (omissis)
    self.dtime = task.deferLater(reactor, 5, self.printData)
    

    只是一些旁注:

    在 sn-p 上方的文本中,您说要在五秒钟后调用 cancelTest,但在代码中您实际上调用了 printData;当然,如果 printData 只是打印一些东西,没有引发并返回一个立即值,这将导致 cancelTest 函数在之后立即执行,因为它是一个链式调用; 但如果你真的想 100% 确定,你应该在 deferLater 中调用 cancelTest,而不是 printData

    另外,我不明白这是否是一种“超时”;请注意,这种回调将在所有情况下触发,即使测试时间少于 5 秒。如果你需要一个可取消的任务,你应该直接使用reactor.callLater;这不会返回您可以使用的 deferred,但会让您取消预定的通话。

    【讨论】:

    • 感谢您的回答。我还有疑问:由于这个程序使用了internet.TCPServer等服务模块,所以反应堆实际上是在幕后,如果我像你说的那样使用反应堆,会不会是2个反应堆?我该怎么办?
    • reactor 实际上是一种模式,在 POSA2 书中有很好的描述:eu.wiley.com/WileyCDA/WileyTitle/productCd-0471606952.html 只有一个反应器。在 Twisted 中,如果您在 Linux 下,您可能正在使用 SelectReactor 或 EPollReactor。第一次导入此类模块时,如果尚未安装默认反应器,它会实例化默认反应器:github.com/twisted/twisted/blob/trunk/src/twisted/internet/… 所以它是 TCPServer,它在后台使用反应器,而不是反之亦然。在需要特定实现之前,您可以放心地忽略它。
    猜你喜欢
    • 2016-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-28
    • 1970-01-01
    • 2012-08-07
    相关资源
    最近更新 更多