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

时间:2016-02-05 15:29:23

标签: python exception twisted deferred

我正在阅读McKellar和Fettig的Twisted Network Programming Essentials, 2nd Ed.

我在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")

$ 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")

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

  

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

我做错了吗?

编辑:

我已将错误显示在我的机器上。

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

import sys
from twisted.python import log

log.startLogging(sys.stdout)

# rest of the code goes here

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

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

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

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

3 个答案:

答案 0 :(得分:1)

我在遇到一个非常类似的问题后找到了这个问题,同时通过Dave Perticola的优秀Twisted Introduction专门在Part 9: A Second Interlude, Deferred中找到了一个类似于你发布的example:< / p>

from twisted.internet.defer import Deferred
def callback(res):
    raise Exception('oops')
d = Deferred()
d.addCallback(callback)
d.callback('Here is your result.')
print "Finished"

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

Finished
Unhandled error in Deferred:
Traceback (most recent call last):
 ...
--- <exception caught here> ---
 ...
exceptions.Exception: oops

我最初在EL6上假设了一个版本问题,Twisted 16和PyPy 5.0.1,但研究引导我到这里;然后在开启记录时,正如另一个答案中所建议的那样,对我认为的实际答案没有影响。

我的答案的线索是在我正在编写的教程中使用以下语句:

  

“完成”首先出现的原因是因为在“延迟垃圾收集 之前,实际上并未打印”未处理“消息。

出于某种原因,对于你我而言,当垃圾收集器到处做它的事情时,它不再有任何输出到的地方。如果你想看到这是真的,这是我修改过的代码:

import gc
from twisted.internet.defer import Deferred
def callback(res):
    raise Exception('oops call')
d = Deferred()
d.addCallback(callback)
d.callback('Here is your result.')
d = None
gc.collect()
print "Finished"

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

答案 1 :(得分:0)

我认为我们的代码没有任何问题。

我在这里跑步:

$ python deferred.py

输出结果为:

Unhandled error in Deferred:


Traceback (most recent call last):
  File "deferred.py", line 8, in <module>
    d.callback("oh no")
  File "/home/vagrant/.virtualenvs/asyncproxy/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 393, in callback
    self._startRunCallbacks(result)
  File "/home/vagrant/.virtualenvs/asyncproxy/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 501, in _startRunCallbacks
    self._runCallbacks()
--- <exception caught here> ---
  File "/home/vagrant/.virtualenvs/asyncproxy/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 588, in _runCallbacks
    current.result = callback(current.result, *args, **kw)
  File "deferred.py", line 4, in raiseErr
    raise Exception(err)
exceptions.Exception: oh no

我正在使用Twisted 15.5.0和Python 2.7.6。

P.S:没有必要初始化日志。没有它就可以工作。

答案 2 :(得分:0)

此代码在我测试过的所有Windows机器上都给出了相同的结果,而且没有任何Linux机器。我的结论是,这是一个与Windows,twisted或pywin32有关的问题。