2010-03-19 8 views
7

Conosci un modo semplice per trovare una chiamata di registrazione che genera "non abbastanza argumenst per la stringa di formato". Sulla mia stazione di lavoro ho modificato logging/__init__.py per stampare il messaggio in modo da poter trovare facilmente la riga nella sorgente.Un modo semplice per trovare "non abbastanza argomenti ..." nella libreria di registrazione python

Ma avete qualche idea su cosa fare nell'ambiente di test in cui non è possibile modificare la libreria standard di Python né eseguire facilmente pdb?

Nota: Il traceback non ha senso ed è in scala dalla libreria di registrazione. Ecco un traceback:

File "/usr/lib/python2.6/logging/handlers.py", line 71, in emit 
    if self.shouldRollover(record): 
    File "/usr/lib/python2.6/logging/handlers.py", line 144, in shouldRollover 
    msg = "%s\n" % 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 enough arguments for format string 

E qui è il codice nella libreria standard che cattura l'errore

try: 
     if self.shouldRollover(record): 
      self.doRollover() 
     logging.FileHandler.emit(self, record) 
    except (KeyboardInterrupt, SystemExit): 
     raise 
    except: 
     self.handleError(record) 

soluzione come suggerito da Alex: ho avvolto il getMessage per stampare il msg e args. Ecco il codice:

def print_log_record_on_error(func): 
    def wrap(self, *args, **kwargs): 
     try: 
      return func(self, *args, **kwargs) 
     except: 
      import sys 
      print >>sys.stderr, "Unable to create log message msg=%r, args=%r " % (
           getattr(self, 'msg', '?'), getattr(self, 'args', '?')) 
      raise 
    return wrap 
import logging 
logging.LogRecord.getMessage = print_log_record_on_error(logging.LogRecord.getMessage) 
+0

Grazie per aver chiesto questa domanda e la soluzione di invio. Quando ho affrontato "TypeError: non ci sono abbastanza argomenti per la stringa di formato" nella quarta volta ho iniziato a cercare un modo intelligente per rilevare queste cose. Il tuo post è stato trovato uno nella prima schermata dei risultati di ricerca di Google. Penso che il modulo di registrazione dovrebbe essere aggiornato per gestire questa eccezione e fornire informazioni su dove nel codice utente si verifica questo problema. – vvladymyrov

+0

@vvladymyrov Benvenuto. Grazie per avermi fatto sapere che il codice è stato utile per ou. –

risposta

2

In generale, il modo migliore per catturare un'eccezione (compreso quello si parla) è quello di mettere il codice sospetto nella clausola try di un'istruzione try/except; nella clausola except è possibile utilizzare il modulo traceback o altri modi per individuare l'istruzione errante.

In caso contrario, le eccezioni non rilevate terminano in sys.excepthook, che è un altro modo che è possibile utilizzare per ottenere un traceback, se necessario.

Tuttavia, non penso che il modulo logging abbia un modo architettato per dirgli "fa propagare le eccezioni" - nel qual caso la tua migliore scommessa, per quanto possa essere sporca, è probabilmente la patch per le scimmie. In altre parole, in genere, è possibile "modificare la libreria standard Python" in fase di runtime, impostando gli identificatori in essa contenuti alle proprie funzioni/classi/ecc. Avvolgendo quelli standard. Ad esempio, se si conosce il problema è con un logging.warning chiamata, un "proof of concept" monkeypatch potrebbe essere:

import logging, traceback 

orgwarn = logging.warning 
def mywarn(msg, *a): 
    try: res = msg % a 
    except TypeError: 
    traceback.print_exc() 
    return orgwarn(msg, *a) 
logging.warning = mywarn 

ci sono modi più puliti, ma può essere un po 'ingombrante (ad esempio, rendere la propria classe logger e impostalo come il root logger). Il patch delle scimmie non è un buon modo per operare in un ambiente di produzione (è fragile per gli aggiornamenti del sistema, può essere difficile da capire e mantenere, ecc.), Ma può essere accettabile a scopo di debug e di test.

+0

Buona idea, ho avvolto la funzione getMessage per stampare msg e args e ho trovato il bug. Grazie. –

0

Per trovare una chiamata di registrazione che genera "non sufficiente argumenst per la stringa di formato".

grep il sorgente per tutte le chiamate di registrazione. Non ce ne sono molti: .info(, .warn(, .debug(, .error(, .critical(, .exception(, .log(.

Uno di questi metodi ha un formato senza argomenti sufficienti. È generalmente facile da individuare, poiché il messaggio avrà operatori di formattazione "%".

Se l'applicazione è coerente nella chiamata di tutti i logger logger rende ancora più semplice, poiché è possibile più semplicemente grep per logger..

Problemi correlati