代码之家  ›  专栏  ›  技术社区  ›  Claudiu

扭曲:无用的“AlreadyCalled”错误

  •  5
  • Claudiu  · 技术社区  · 14 年前

    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 回复  |  直到 14 年前
        1
  •  7
  •   Jean-Paul Calderone    14 年前

    如果您没有任何关于出错原因的其他提示(比如您的单元测试指出了导致这种情况的具体案例,或者如果pyfunc的回答没有明确说明为什么会发生这种情况),那么启用延迟调试以获取有关指定延迟调试的第一个(也是唯一允许的)结果的位置的信息:

    from twisted.internet import defer
    defer.setDebugging(True)
    

    或者

    twistd --debug [...]
    

    或者

    trial --debug [...]
    

    您将获得额外的堆栈跟踪和错误报告,就像您遇到的那样。额外的堆栈跟踪将告诉您问题中的延迟是在何处创建的,以及它第一次被调用的位置(对它调用了.callback()或.errback())。

    inlineCallbacks ,您无法获得有关实际错误发生位置的良好堆栈跟踪,但有关延迟的第一次触发位置的信息可能会提示您后续激活可能来自何处。

    不幸的是,增加的模糊性只是使用的成本 内联回调 目前。这也许是可以克服的,但需要有人来承担这项任务。

        2
  •  2
  •   pyfunc    14 年前

    我猜在您的代码中,您显式地调用了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
    

    在你的代码中检查这种多次开火的可能性。这可能就是问题所在。