如何让扭曲打印未处理错误的确切位置

时间:2017-04-23 22:56:10

标签: python twisted

我正在编写一个简单的服务器程序。它们将是新鲜代码中不可避免的拼写错误和其他错误,通常python解释器将打印ValueError / AttributeError回溯并退出。回溯可以指向错误的确切位置。但是,在扭曲的框架下,不会打印这些错误。如下例所示:

from twisted.internet import reactor, protocol, task
#from twisted.internet.defer import setDebugging
#setDebugging(True)

class MyProtocol(protocol.Protocol):
    def dataReceived(self, data):
        try:
            set_position(int(data))
        except ValueError:
            pass
    def connectionMade(self):
        self.factory.clientConnectionMade(self)
    def connectionLost(self, reason):
        self.factory.clientConnectionLost(self)

class MyFactory(protocol.Factory):
    protocol = MyProtocol
    def __init__(self):
        self.clients = []
        self.lc = task.LoopingCall(self.announce)
        self.lc.start(1)

    def announce(self):
        pos = A_GREAT_TYPO_HERE()
        for client in self.clients:
            client.transport.write("Posiiton is {0}\n".format(pos).encode('utf-8'))

    def clientConnectionMade(self, client):
        self.clients.append(client)

    def clientConnectionLost(self, client):
        self.clients.remove(client)

def get_position():
    return position[0]

def set_position(pos):
    position[0] = pos

def main():
    global position
    position = [0]
    myfactory = MyFactory()
    reactor.listenTCP(5362, myfactory)
    reactor.run()

if __name__ == "__main__":
    main()
MyFactory.announce中的

A_GREAT_TYPO_HERE()应为get_position()。但这是一个错字。

当服务器运行时,终端只输出

Unhandled error in Deferred:

,没有别的。即使我启用延迟调试(取消注释第2和第3行),终端输出:

Unhandled error in Deferred:
(debug:  C: Deferred was created:
 C:  File "nodes/test.py", line 48, in <module>
 C:    main()
 C:  File "nodes/test.py", line 43, in main
 C:    myfactory = MyFactory()
 C:  File "nodes/test.py", line 21, in __init__
 C:    self.lc.start(1)
 C:  File "/home/sgsdxzy/anaconda3/lib/python3.6/site-packages/twisted/internet/task.py", line 189, in start
 C:    deferred = self._deferred = defer.Deferred()
 I: First Invoker was:
 I:  File "nodes/test.py", line 48, in <module>
 I:    main()
 I:  File "nodes/test.py", line 43, in main
 I:    myfactory = MyFactory()
 I:  File "nodes/test.py", line 21, in __init__
 I:    self.lc.start(1)
 I:  File "/home/sgsdxzy/anaconda3/lib/python3.6/site-packages/twisted/internet/task.py", line 194, in start
 I:    self()
 I:  File "/home/sgsdxzy/anaconda3/lib/python3.6/site-packages/twisted/internet/task.py", line 241, in __call__
 I:    d.addErrback(eb)
 I:  File "/home/sgsdxzy/anaconda3/lib/python3.6/site-packages/twisted/internet/defer.py", line 332, in addErrback
 I:    errbackKeywords=kw)
 I:  File "/home/sgsdxzy/anaconda3/lib/python3.6/site-packages/twisted/internet/defer.py", line 310, in addCallbacks
 I:    self._runCallbacks()
 I:  File "/home/sgsdxzy/anaconda3/lib/python3.6/site-packages/twisted/internet/defer.py", line 653, in _runCallbacks
 I:    current.result = callback(current.result, *args, **kw)
 I:  File "/home/sgsdxzy/anaconda3/lib/python3.6/site-packages/twisted/internet/task.py", line 236, in eb
 I:    d.errback(failure)
)

它将错误指向self.lc.start(1),但不是A_GREAT_TYPO_HERE()。如何调试我的程序,以便回溯可以指向实际错误?

1 个答案:

答案 0 :(得分:0)

&#34; C&#34;和&#34;我&#34;您看到的行是由于您启用了延迟调试。 &#34; C&#34; lines为您提供创建Deferred的堆栈。 &#34;我&#34; line为你提供了Deferred被调用的堆栈&#34; (调用了callbackerrback方法。)

看来,这些都不是你正在寻找的。如果你想看到与被驱逐的Failure相关联的堆栈,最直接的解决方案是确保Failure被记录(并且你有一个日志观察者,这样你就可以实际上看到了日志事件。

您应该将其添加到main

from sys import stdout
from twisted.logger import globalLogBeginner, textFileLogObserver
globalLogBeginner.beginLoggingTo([textFileLogObserver(stdout)])

这会将日志流作为文本引导到stdout。最有可能获得您想要的信息。但是,为了确保安全,您还需要显式记录故障,而不是依赖垃圾收集器为您执行此操作。所以你也想改变:

self.lc.start(1)

要:

# Module scope
from twisted.logger import Logger
logger = Logger()

...

# in __init__
d = self.lc.start(1)
d.addErrback(lambda f: logger.failure("Loop thing problem", f))

(另外,您可能需要考虑从__init__中取出此代码并将其放入startFactory;也可以考虑不使用全局反应器,而是将其作为参数传递。)

这将为您提供如下输出:

2017-04-25T06:53:14-0400 [__main__.MyFactory#critical] Foo
        Traceback (most recent call last):
          File "debugging2.py", line 52, in main
            myfactory = MyFactory()
          File "debugging2.py", line 28, in __init__
            d = self.lc.start(1)
          File "/tmp/debugging/local/lib/python2.7/site-packages/twisted/internet/task.py", line 194, in start
            self()
          File "/tmp/debugging/local/lib/python2.7/site-packages/twisted/internet/task.py", line 239, in __call__
            d = defer.maybeDeferred(self.f, *self.a, **self.kw)
        --- <exception caught here> ---
          File "/tmp/debugging/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 150, in maybeDeferred
            result = f(*args, **kw)
          File "debugging2.py", line 32, in announce
            pos = A_GREAT_TYPO_HERE()
        exceptions.NameError: global name 'A_GREAT_TYPO_HERE' is not defined