2011-02-26 15 views
7

Quando ho un sacco di diversi moduli usando il modulo di registrazione standard di Python, la seguente analisi dello stack fa ben poco per aiutarmi a trovare dove, esattamente, ho avuto una dichiarazione di registro male formata:Trovare la fonte di errori di formato quando si utilizza python registrazione

Traceback (most recent call last): 
    File "/usr/lib/python2.6/logging/__init__.py", line 768, in emit 
    msg = self.format(record) 
    File "/usr/lib/python2.6/logging/__init__.py", line 648, in format 
    return fmt.format(record) 
    File "/usr/lib/python2.6/logging/__init__.py", line 436, in format 
    record.message = record.getMessage() 
    File "/usr/lib/python2.6/logging/__init__.py", line 306, in getMessage 
    msg = msg % self.args 
TypeError: not all arguments converted during string formatting 

Sto solo iniziando a utilizzare il modulo di registrazione di Python, quindi forse sto trascurando qualcosa di ovvio. Non sono sicuro se lo stack-trace è inutile perché sto usando greenlets, o se questo è normale per il modulo di registrazione, ma qualsiasi aiuto sarebbe apprezzato. Sarei disposto a modificare la fonte, qualsiasi cosa per fare in modo che la libreria di logging dia effettivamente indicazioni su dove si trova il problema.

risposta

5

Il modulo di registrazione è progettato per impedire ai messaggi di registro non validi di eliminare il resto del codice, pertanto il metodo emit rileva gli errori e li passa a un metodo handleError. La cosa più facile da fare per voi sarebbe quella di modificare temporaneamente /usr/lib/python2.6/logging/__init__.py, e trovare handleError. Assomiglia a questo:

def handleError(self, record): 
    """ 
    Handle errors which occur during an emit() call. 

    This method should be called from handlers when an exception is 
    encountered during an emit() call. If raiseExceptions is false, 
    exceptions get silently ignored. This is what is mostly wanted 
    for a logging system - most users will not care about errors in 
    the logging system, they are more interested in application errors. 
    You could, however, replace this with a custom handler if you wish. 
    The record which was being processed is passed in to this method. 
    """ 
    if raiseExceptions: 
     ei = sys.exc_info() 
     try: 
      traceback.print_exception(ei[0], ei[1], ei[2], 
             None, sys.stderr) 
      sys.stderr.write('Logged from file %s, line %s\n' % (
          record.filename, record.lineno)) 
     except IOError: 
      pass # see issue 5971 
     finally: 
      del ei 

Ora modificarlo temporaneamente. Inserimento di un semplice raise alla partenza dovrebbe garantire l'errore viene propogated il vostro codice, invece di essere inghiottito. Una volta risolto il problema, è sufficiente ripristinare il codice di registrazione su quello che era.

6

Invece di modificare il codice python installato, è possibile anche trovare gli errori come questo:

def handleError(record): 
     raise RuntimeError(record) 
    handler.handleError = handleError 

cui gestore è uno dei gestori che sta dando il problema. Ora quando si verifica l'errore di formattazione, vedrai la posizione.

+0

Beh, è ​​un modo orribile per farlo, tuttavia è un approccio che vale la pena ricordare per quei casi in cui la modifica della libreria è completamente impossibile, quindi +1 – porgarmingduod

+0

@porgarmingduod: Monkey-patching può non essere grandioso, ma non è affatto più orribile che manipolare la fonte del li standard brary. Le patch delle scimmie influenzeranno tutto il resto nello stesso processo, ma la modifica diretta della libreria interesserà tutto il resto dello stesso sistema. –

1

In alternativa è possibile creare un formattatore di tuo, ma poi si deve includere ovunque.

class DebugFormatter(logging.Formatter): 
    def format(self, record): 
     try: 
      return super(DebugFormatter, self).format(record) 
     except: 
      print "Unable to format record" 
      print "record.filename ", record.filename 
      print "record.lineno ", record.lineno 
      print "record.msg ", record.msg 
      print "record.args: ",record.args 
      raise 


FORMAT = '%(levelname)s %(filename)s:%(lineno)d %(message)s' 
formatter = DebugFormatter(FORMAT) 
handler = logging.StreamHandler() 
handler.setLevel(logging.DEBUG) 
handler.setFormatter(formatter) 
logger = logging.getLogger(__name__) 
logger.setLevel(logging.DEBUG) 
logger.addHandler(handler) 
3

non è proprio una risposta alla domanda, ma si spera che saranno altri principianti, con il modulo di registrazione come me.

Il mio problema è che ho sostituito tutte le occorrenze di stampa con logging.info, così una linea valida come print('a',a) divennero logging.info('a',a) (ma dovrebbe essere logging.info('a %s'%a) invece.

Ciò è stato anche accennato nel How to traceback logging errors?, ma doesn Venite nella ricerca

+1

nuova sintassi in Python 3.6: 'logging.info (f'a {a} ')' – JinSnow

+0

grazie, non avevo guardato dentro! https://www.python.org/dev/peps/pep-0498/ – lib

Problemi correlati