twisted: 无用的“已调用”错误
我这个奇怪的Python程序总是时不时地出现这个信息:
Unhandled error in Deferred:
Traceback (most recent call last):
File "c:\python25\lib\site-packages\twisted\internet\defer.py", line 757, in gotResult
_inlineCallbacks(r, g, deferred)
File "c:\python25\lib\site-packages\twisted\internet\defer.py", line 747, in _inlineCallbacks
deferred.errback()
File "c:\python25\lib\site-packages\twisted\internet\defer.py", line 269, in errback
self._startRunCallbacks(fail)
File "c:\python25\lib\site-packages\twisted\internet\defer.py", line 312, in _startRunCallbacks
self._runCallbacks()
--- <exception caught here> ---
File "c:\python25\lib\site-packages\twisted\internet\defer.py", line 328, in _runCallbacks
self.result = callback(self.result, *args, **kw)
File "c:\python25\lib\site-packages\twisted\internet\defer.py", line 243, in callback
self._startRunCallbacks(result)
File "c:\python25\lib\site-packages\twisted\internet\defer.py", line 298, in _startRunCallbacks
raise AlreadyCalledError
twisted.internet.defer.AlreadyCalledError:
这个信息对我来说没什么帮助,因为它没有指向我的源代码... 我还在用defer.inlineCallbacks
。你知道可能出了什么问题吗?
2 个回答
2
我想你代码中的某个地方,可能是你在明确地调用了一个叫做“deferred”的回调。而且这个回调被调用了多次。其实,deferred的回调只能被触发一次,这个回调的作用是表示一个长时间等待的任务已经完成,可能是出错了,也可能是成功了。如果你试图多次触发这个deferred,Twisted会有机制来抛出上述的错误。
看看下面这段代码:
from twisted.internet.defer import Deferred
def func(x): print x
d = Deferred()
d.addCallbacks(func, func)
d.callback('First fire')
d.callback('Second fire')
这段代码会导致以下错误:
raise AlreadyCalledError
twisted.internet.defer.AlreadyCalledError
请检查一下你的代码,看看是否有多次触发的情况。这可能就是问题所在。
7
如果你没有其他线索来判断问题出在哪里(比如你的单元测试指出了具体导致问题的情况,或者pyfunc的回答没有让你明白为什么会这样),那么可以启用延迟调试,这样可以获取关于延迟对象(Deferred)第一个(也是唯一允许的)结果是在哪里被指定的信息:
from twisted.internet import defer
defer.setDebugging(True)
或者
twistd --debug [...]
或者
trial --debug [...]
这样你会得到额外的错误报告和堆栈追踪信息,类似于你遇到的那个错误。额外的堆栈追踪会告诉你这个延迟对象是在哪里创建的,以及它第一次被调用(调用了.callback()或.errback())的地方。
因为你在使用inlineCallbacks
,所以你不会得到一个清晰的堆栈追踪来告诉你实际错误发生的位置,但关于延迟对象第一次被触发的信息可能会给你一些线索,帮助你找到后续激活的来源。
不幸的是,使用inlineCallbacks
目前带来的一些模糊性是不可避免的。这可能是可以解决的,但需要有人来承担这个任务。