【问题标题】:Twisted Deferred.addCallBack() vs. yield and @inlineDeferredTwisted Deferred.addCallBack() 与 yield 和 @inlineDeferred
【发布时间】:2010-10-08 21:00:20
【问题描述】:

有什么理由使用其中一个吗?

他们有同样的表现吗?

【问题讨论】:

    标签: python twisted


    【解决方案1】:

    例如,我倾向于使用inlineCallbacks 对某些服务进行多步初始化(例如身份验证),其中每个后续步骤都取决于上一步的结果。除了这些情况,我倾向于发现 inlineCallbacks 可能会导致懒惰的编程,从而减慢你的应用程序。

    这是一个例子:

    @defer.inlineCallbacks
    def some_func():
        res1 = yield call1()
        res2 = yield call2()
        ... do something with res1 and res2 ...
    

    如果 call1call2 是您想要并行化的完全独立的调用,则此函数将结束序列化这些调用。要将其转换为并行调用,您应该:

    @defer.inlineCallbacks
    def some_func_better():
        d1 = call1()
        d2 = call2()
        res1 = yield d1
        res2 = yield d2
    

    通过这种方式,您可以同时运行 call1 和 call2,但您会在结果出现时等待结果。因此,虽然可以从库存延期中获得相同的好处,但 inlineCallbacks 似乎太容易了执行前一个解决方案。

    另外,请记住,您仍然必须将 try...except 块包裹在所有 yield 调用中,因为它们是在代码中捕获错误返回的唯一方法(除非 inlineCallbacks 函数的调用函数处理错误返回该级别)。

    所以,我发现这实际上并不是性能本身的问题,而是让我推荐反对inlineCallbacks的好习惯一般 - 他们是仍然适用于快速代码 sn-ps、多阶段初始化例程或测试。

    【讨论】:

    • 令人惊讶的是inlineCallbacks 不支持cancel()。由于我需要cancel() 进程的能力,我曾经不得不将几个准备读取的函数重写为嵌套回调的混乱结构。
    【解决方案2】:

    差异应该非常微妙。如果这段代码确实经常运行那么重要,那么也许您应该研究一下您的应用程序设计。否则,选择更易于阅读的变体,您必须在几个月或几年后对它做出正面和反面。

    编辑:如果你真的想知道,这里是你如何找到的(毕竟,它可能是特定于你的 python 版本的实现):在一个紧密的循环中运行这两个版本并测量时间。增加循环计数,直到版本之间的时间差远大于同一版本在多次运行中的时间方差。更改 python 版本、操作系统等后重复。

    【讨论】:

    • 另外,对您自己的应用程序代码进行测试会更有用,因为这取决于您如何使用这些代码。
    【解决方案3】:

    使用 defer.inlineCallbacks 可以让你的代码更容易阅读..

    它有点像 corountine 风格:你既不阻塞调用也不使用回调链来构建整个逻辑。它很直观。

    【讨论】:

      猜你喜欢
      • 2011-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-11
      • 2013-11-11
      • 2013-04-06
      • 2013-01-09
      • 1970-01-01
      相关资源
      最近更新 更多