【问题标题】:What does @defer.inlineCallbacks mean when I don't need yield return a value?当我不需要 yield 返回值时,@defer.inlineCallbacks 是什么意思?
【发布时间】:2015-03-05 05:50:24
【问题描述】:
在scrapy.core.engine
ExecutionEngine 方法启动
@defer.inlineCallbacks
def start(self):
"""Start the execution engine"""
assert not self.running, "Engine already running"
self.start_time = time()
yield self.signals.send_catch_log_deferred(signal=signals.engine_started)
self.running = True
self._closewait = defer.Deferred()
yield self._closewait
为什么不直接使用self.signals.send_catch_log_deferred(signal=signals.engine_started),而是使用yield?
【问题讨论】:
标签:
python
scrapy
deferred
【解决方案1】:
为什么不直接使用self.signals.send_catch_log_deferred(signal=signals.engine_started),而是使用yield?
因为send_catch_log_deferred 返回一个Deferred 对象。如果你想避免在那里出现yield,那么你应该使用send_catch_log,但使用send_catch_log_deferred的目的是让听众返回Deferred对象。
使用send_catch_log 的信号无法返回Deferred 对象,因此它们不允许执行异步操作。
编辑:有关inlineCallbacks 的详细介绍,请参阅:http://krondo.com/?p=2441
【解决方案2】:
@defer.inlineCallbacks 期望修饰函数是生成器函数,并且在修饰函数内部调用生成器函数(甚至返回一个)不会使该函数成为生成器函数。调查:
def gen():
yield 1
def func(): return gen
import dis
dis.dis(gen)
2 0 LOAD_CONST 1 (1)
3 YIELD_VALUE
4 POP_TOP
5 LOAD_CONST 0 (None)
8 RETURN_VALUE
dis.dis(func)
1 0 LOAD_GLOBAL 0 (gen)
3 RETURN_VALUE
import inspect
inspect.isgeneratorfunction(gen)
True
inspect.isgeneratorfunction(func)
False
因此,满足 @defer.inlineCallbacks 的唯一方法是 yield 从 self.signals.send_catch_log_deferred(signal=signals.engine_started) 或从其他地方延迟。