Twisted Deferred不显示没有errback的未处理异常

Mon*_*pit 5 python exception twisted deferred

我正在阅读McKellar和Fettig的Twisted Network Programming Essentials,第二版.

我在Windows 7上运行Python 2.7.10上的Twisted 15.5.0.

在关于Deferred有一个应该引发的示例的部分中Unhandled Error in Deferred- 但是当我运行下面的最小示例时,我只是从控制台完全沉默:

最小的例子

from twisted.internet.defer import Deferred

def raiseErr(err):
    raise Exception(err)

d = Deferred()
d.addCallback(raiseErr)
d.callback("oh no")
Run Code Online (Sandbox Code Playgroud)

$ python test.py (no output)

实际书籍文本中的最小示例

本书的实际例子如下:

from twisted.internet.defer import Deferred

def callback1(result):
    print "Callback 1 said:", result
    return result

def callback2(result):
    print "Callback 2 said:", result

def callback3(result):
    raise Exception("Callback 3")

def errback1(failure):
    print "Errback 1 had an an error on", failure
    return failure

d = Deferred()
d.addCallback(callback1)
d.addCallback(callback2)
d.addCallback(callback3)
d.callback("Test")
Run Code Online (Sandbox Code Playgroud)

预期的输出在本书中列为:

callback3引发一个Exception,并且因为没有注册errback来处理Exception,程序终止并向Unhandled Error用户报告.结果是:

Callback 1 said: Test
Callback 2 said: Test
Unhandled error in Deferred:
Unhandled Error
Traceback (most recent call last):
File "/tmp/test.py", line 33, in <module>
d.callback("Test")
<...>
File "/tmp/test.py", line 11, in callback3
raise Exception("Callback 3")
exceptions.Exception: Callback 3
Run Code Online (Sandbox Code Playgroud)

难道我做错了什么?

编辑:

我已经错误地在我的机器上正确显示了.

要在没有对象的errback处理程序的情况下记录错误Deferred,我需要将以下内容添加到我的代码段:

import sys
from twisted.python import log

log.startLogging(sys.stdout)

# rest of the code goes here
Run Code Online (Sandbox Code Playgroud)

现在,当我从我的问题中的第一个代码片段运行我的最小示例时,我得到以下输出:

2016-02-05 09:45:43-0600 [-] Log opened.
2016-02-05 09:45:43-0600 [-] Invalid format string or unformattable object in log message: '%(log_legacy)s', {'format': '%(log_legacy)s', 'log_legacy': <twisted.logger._stdlib.StringifiableFromEvent object at 0x038913F0>, 'time': 1454687143.778, 'message': (), 'log_time': 1454687143.778, 'log_namespace': 'twisted.internet.defer', 'log_level': <LogLevel=critical>, 'log_source': None, 'system': '-', 'isError': True, 'log_logger': <Logger 'twisted.internet.defer'>, 'log_format': 'Unhandled error in Deferred:'}
2016-02-05 09:45:43-0600 [-] Unhandled Error
        Traceback (most recent call last):
          File "testd.py", line 13, in <module>
            d.callback("oh no")
          File "C:\Swat\.virtualenvs\twisted\lib\site-packages\twisted\internet\defer.py", line 393, in callback
            self._startRunCallbacks(result)
          File "C:\Swat\.virtualenvs\twisted\lib\site-packages\twisted\internet\defer.py", line 501, in _startRunCallbacks
            self._runCallbacks()
        --- <exception caught here> ---
          File "C:\Swat\.virtualenvs\twisted\lib\site-packages\twisted\internet\defer.py", line 588, in _runCallbacks
            current.result = callback(current.result, *args, **kw)
          File "testd.py", line 9, in raiseErr
            raise Exception(err)
        exceptions.Exception: oh no
Run Code Online (Sandbox Code Playgroud)

所以,现在我可以验证Twisted是否确实引发了错误 - 它只是因为某些原因而不想告诉我.如果任何人都可以详细说明为什么在没有定义错误的情况下处理异常的默认情况,我很想知道.

我改变了标题以反映我的新问题.

Dan*_*Sut 1

我在完成 Dave Perticola 出色的Twisted 介绍(特别是在第 9 部分:第二个插曲,延迟)时遇到了一个非常类似的问题后发现了这个问题,他有一个与您发布的示例类似的示例:

\n\n
from twisted.internet.defer import Deferred\ndef callback(res):\n    raise Exception(\'oops\')\nd = Deferred()\nd.addCallback(callback)\nd.callback(\'Here is your result.\')\nprint "Finished"\n
Run Code Online (Sandbox Code Playgroud)\n\n

就像你一样,我没有得到建议的输出:

\n\n
Finished\nUnhandled error in Deferred:\nTraceback (most recent call last):\n ...\n--- <exception caught here> ---\n ...\nexceptions.Exception: oops\n
Run Code Online (Sandbox Code Playgroud)\n\n

我最初假设版本控制问题,Twisted 16 with PyPy 5.0.1 on EL6 对我来说,但研究引导我到了这里;然后,当打开日志记录时,正如另一个答案中所建议的那样,对我认为的实际答案没有影响。

\n\n

我的答案的线索是在我正在使用的教程中,其中包含以下声明:

\n\n
\n

\xe2\x80\x9cFinished\xe2\x80\x9d 首先出现的原因是 \xe2\x80\x9cUnhandled\xe2\x80\x9d 消息在延迟被垃圾收集之前才实际打印。

\n
\n\n

出于某种原因,对于你和我来说,当垃圾收集器开始做它的事情时,它不再有任何地方可以输出。如果你想看看这是真的,这是我修改后的代码:

\n\n
import gc\nfrom twisted.internet.defer import Deferred\ndef callback(res):\n    raise Exception(\'oops call\')\nd = Deferred()\nd.addCallback(callback)\nd.callback(\'Here is your result.\')\nd = None\ngc.collect()\nprint "Finished"\n
Run Code Online (Sandbox Code Playgroud)\n\n

我想真正的答案是在垃圾收集器到达之前处理您的异常,但也许这一点信息会让您睡得更轻松,即使我们不知道为什么它对某些人有效,我们知道什么是导致我们预期的错误消息消失。

\n