【发布时间】:2010-10-08 21:00:20
【问题描述】:
有什么理由使用其中一个吗?
他们有同样的表现吗?
【问题讨论】:
有什么理由使用其中一个吗?
他们有同样的表现吗?
【问题讨论】:
例如,我倾向于使用inlineCallbacks 对某些服务进行多步初始化(例如身份验证),其中每个后续步骤都取决于上一步的结果。除了这些情况,我倾向于发现 inlineCallbacks 可能会导致懒惰的编程,从而减慢你的应用程序。
这是一个例子:
@defer.inlineCallbacks
def some_func():
res1 = yield call1()
res2 = yield call2()
... do something with res1 and res2 ...
如果 call1 和 call2 是您想要并行化的完全独立的调用,则此函数将结束序列化这些调用。要将其转换为并行调用,您应该:
@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() 进程的能力,我曾经不得不将几个准备读取的函数重写为嵌套回调的混乱结构。
差异应该非常微妙。如果这段代码确实经常运行那么重要,那么也许您应该研究一下您的应用程序设计。否则,选择更易于阅读的变体,您将必须在几个月或几年后对它做出正面和反面。
编辑:如果你真的想知道,这里是你如何找到的(毕竟,它可能是特定于你的 python 版本的实现):在一个紧密的循环中运行这两个版本并测量时间。增加循环计数,直到版本之间的时间差远大于同一版本在多次运行中的时间方差。更改 python 版本、操作系统等后重复。
【讨论】:
使用 defer.inlineCallbacks 可以让你的代码更容易阅读..
它有点像 corountine 风格:你既不阻塞调用也不使用回调链来构建整个逻辑。它很直观。
【讨论】: