9

当扭曲反应器正在运行并且在未捕获的延迟中发生异常时,“未处理的错误”将与回溯和异常一起打印到终端。是否可以处理/拦截这些异常(例如,设置回调或覆盖方法)?

编辑:我知道我可以通过将 errback 添加到 deferrerd 来捕获失败。我想知道的是,是否有办法拦截一个未处理的故障/异常,该故障/异常已经沿着链向上到达反应堆。

编辑:本质上,我想知道扭曲反应器是否有全局错误处理程序或可以访问的东西。我想知道,因为它会打印故障的回溯和错误。

例子:

Unhandled Error
Traceback (most recent call last):
  File "/var/projects/python/server.py", line 359, in run_server
    return server.run()
  File "/var/projects/python/server.py", line 881, in run
    reactor.run()
  File "/usr/local/lib/python2.6/dist-packages/Twisted-11.0.0-py2.6-linux-x86_64.egg/twisted/internet/base.py", line 1162, in run
    self.mainLoop()
  File "/usr/local/lib/python2.6/dist-packages/Twisted-11.0.0-py2.6-linux-x86_64.egg/twisted/internet/base.py", line 1171, in mainLoop
    self.runUntilCurrent()
--- <exception caught here> ---
  File "/usr/local/lib/python2.6/dist-packages/Twisted-11.0.0-py2.6-linux-x86_64.egg/twisted/internet/base.py", line 793, in runUntilCurrent
    call.func(*call.args, **call.kw)
  File "/var/projects/python/server.py", line 524, in monitor
    elapsed = time.time() - info.last
exceptions.NameError: global name 'info' is not defined
4

3 回答 3

6

因为这些回溯是使用调用来编写的twisted.python.log.deferr()(无论如何在 Twisted 10.2 中),所以可以使用日志观察器重定向它们。这是与这些堆栈跟踪最常见的事情。我找不到任何日志观察者的基类(令人惊讶),但有几个内置:

twisted.python.log.PythonLoggingObserver- 任何记录到标准 Pythonlogging模块。(我在我的应用程序中使用它。)

twisted.python.log.FileLogObserver- 任何记录的内容都会写入文件。

这两个都将捕获反应堆报告的堆栈跟踪。您所要做的就是构造日志观察器(无参数),然后调用对象的start()方法。

(旁注:还有一个StdioOnnaStick类,你可以构造和分配,sys.stdout或者sys.stderr如果你想。然后你print去 Twisted 日志的任何东西。)

要真正真正地拦截这些调用,因此根本不会记录堆栈跟踪,您可以:

  • 子类化twisted.internet.SelectReactor并覆盖它的runUntilCurrent()方法。这就是记录堆栈跟踪的内容。twisted.internet.base.ReactorBase在执行此操作之前,您需要研究其来源。
  • 完成所有twisted.*导入后,设置twisted.python.log.deferr为您选择的与原型兼容的功能def err(_stuff=None, _why=None, **kw)
于 2011-08-05T22:08:30.910 回答
3

您可以将 errback 添加到 deferred;未处理的异常会自动转换为twisted.python.failure.Failure.

于 2011-08-05T21:19:14.307 回答
1

回复您的评论:

本质上,我想知道扭曲反应器是否具有全局错误处理程序或可以访问的东西。我想知道,因为它会打印故障的回溯和错误。

回应是“不正确”。

首先,reactor 与 deferred 无关,实际上应该将整个 deferred 模块放在twisted.python包中,但由于某些依赖关系,目前还不能这样做。回到你的问题...

深入研究扭曲的代码(更准确地说是twisted.internet.defer模块),您可以概述以下事件流:

  1. callback方法被调用并有结果时,延迟实例开始通过该_runCallbacks方法运行它的回调;
  2. 如果其中一个回调抛出异常,则将其包装到失败中(第542行);
  3. 如果回调链耗尽并且最后一个结果是失败,则将当前结果分配给DebugInfo实例的 failResult 属性(第575行);
  4. 如果延迟实例及其DebugInfo实例被垃圾回收,结果仍然存在活动故障,DebugInfo.__del__则调用该方法并打印回溯。

鉴于这些前提,最简单的解决方案之一是对DebugInfo类进行猴子补丁:

from twisted.internet.defer import DebugInfo
del DebugInfo.__del__  # Hides all errors
于 2011-08-05T22:12:19.203 回答