2017-04-23 2 views
0

J'écris un programme serveur simple. Ils seront des fautes de frappe inévitables et d'autres erreurs dans le code frais, et habituellement l'interpréteur python imprimera une traceError/AttributeError et quittera. Le retraçage peut pointer vers la position exacte de l'erreur. Cependant, dans le cadre tordu, ces erreurs ne sont pas imprimées. Comme dans l'exemple suivant:Comment laisser tordu imprimer les positions exactes des erreurs non gérées

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() 

A_GREAT_TYPO_HERE() dans MyFactory.announce est censé être get_position(). Mais c'est une faute de frappe.

Et lorsque le serveur est exécuté, le terminal ne sort que

Unhandled error in Deferred:

et rien d'autre. Même si j'activer le débogage Defer (décommenter la 2e et 3e ligne), les sorties de terminaux:

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

Il signale l'erreur aussi près à self.lc.start(1), mais pas A_GREAT_TYPO_HERE(). Comment puis-je déboguer mon programme afin que les retraits puissent pointer vers des erreurs réelles?

+0

Quelle version de Twisted utilisez-vous? –

+0

@ Jean-Paul Calderone c'est 17.1.0, et la version python est 3.6.1 – Light

Répondre

0

Les lignes "C" et "I" que vous voyez sont dues au fait que vous avez activé le débogage différé. Les lignes "C" vous donnent la pile où le différé a été créé. Les lignes "I" vous donnent la pile où le différé a été "invoqué" (sa méthode callback ou errback a été appelée).

Aucun de ceux-ci n'est ce que vous cherchez, semble-t-il. Si vous voulez voir la pile associée au Failure avec le différé, la solution la plus simple est de vous assurer que le Failure est enregistré (et que vous avez un observateur de journal pour que vous puissiez réellement voir cet événement de journal).

Vous devez ajouter à votre main:

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

Ce dirige le flux de journal à stdout sous forme de texte. Il est très probablement suffisant pour vous obtenir l'information que vous voulez. Cependant, pour être vraiment sûr, vous devez également consigner explicitement les échecs au lieu de compter sur le garbage collector pour le faire pour vous. Donc, vous voulez aussi changer:

self.lc.start(1) 

Pour:

# 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)) 

(Aussi, vous voudrez peut-être envisager de prendre ce code de __init__ et de le mettre en startFactory lieu, également envisager de ne pas utiliser un réacteur global mais au lieu de passer autour comme paramètre)

Cela vous donnera une sortie comme:.

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 
+0

Merci! L'enregistreur donne beaucoup d'informations utiles, je vais lire la documentation sur ce qu'il peut offrir. – Light