2016-05-05 53 views
5

C'è un modo per mostrare solo i percorsi di directory importanti quando si esegue un programma python?python3: non mostrare il percorso completo della directory sul messaggio di errore

Attualmente ottengo questo:

python3 foo.py           
Traceback (most recent call last): 
    File "foo.py", line 60, in <module> 
    foo = Foo() 
    File "foo.py", line 22, in __init__ 
    self._run() 
    File "/media/MyDocuments/xxxxxxx/yyyyyyyyy/python_code/foo.py", line 18, in check_input 
    bar = obj.get_action() 
AttributeError: 'obj' object has no attribute 'get_action' 

Per quanto ne so in quale directory il mio codice è, la directory piena rende il messaggio di errore appena peggio leggibile. Posso dire a python di mostrarmi l'output più simile a questo?

python3 foo.py           
    Traceback (most recent call last): 
     File "foo.py", line 60, in <module> 
     foo = Foo() 
     File "foo.py", line 22, in __init__ 
     self._run() 
     File ".../foo.py", line 18, in check_input 
     bar = obj.get_action() 
    AttributeError: 'obj' object has no attribute 'get_action' 

risposta

Utilizzando il codice da unutbu ho aggiunto alcune linee per i colori, nel caso in cui qualcuno è alla ricerca di un facile miglioramento della produzione interprete, basta usare questo come un modulo e importarlo:

import sys 
import traceback 
import os 
import re 

RED = '\033[91m' 
GREEN = '\033[92m' 
YELLOW = '\033[93m' 
LIGHT_PURPLE = '\033[94m' 
PURPLE = '\033[95m' 
CYAN = '\033[96m' 
END = '\033[0m' 

def my_excepthook(type, value, tb): 
    lines = traceback.format_list(traceback.extract_tb(tb)) 
    def shorten(match): 
     return 'File "{}"'.format(os.path.basename(match.group(1))) 
    lines = [re.sub(r'File "([^"]+)"', shorten, line) for line in lines] 
    _print_color(lines) 
    # print(''.join(lines)) 
    print(RED + '{}: {}'.format(type.__name__, value) + END) 

sys.excepthook = my_excepthook 


def _print_color(lines): 
    for l in lines: 
     for i in range(len(l)-1): 
      if l[i:i+5]=="line ": 
       i +=5 
       # Find the length of the number 
       numLen = 0 
       while l[i+numLen].isdigit(): 
        numLen +=1 

       # Find the length of the function 
       funLen = 0 
       while not l[i+numLen+4 + funLen]=="\n": 
        funLen+=1 

       l = ''.join([l[:i], 
         YELLOW+"{}".format(l[i:i+numLen])+END, 
         l[i+numLen:i+numLen+5], 
         LIGHT_PURPLE+"{}".format(l[i+numLen+5:i+numLen+5+funLen])+END, 
         CYAN+"{}".format(l[i+numLen+5+funLen:])+END]) 
       print(l,end="") 
       break 
    print("") 
+1

Puoi fornire un programma breve e completo che produca un pasticcio età come quella? Non riesco a riprodurre i risultati: tutti i miei traceback dicono "foo.py", proprio come le prime due righe del tuo traceback. –

+0

Tutto il mio codice viene salvato nella stessa directory, quindi qualsiasi esempio produrrebbe questo tipo di messaggio di errore sul mio computer. Sto usando Ubuntu, python3, forse un altro sistema operativo utilizza un interprete python standard diverso. – Jonas

risposta

4

Si potrebbe assegnare una funzione personalizzata per sys.excepthook-handle all uncaught exceptions:

sys.excepthook = my_excepthook 

allora si potrebbe utilizzare

def my_excepthook(type, value, tb): 
    lines = traceback.format_list(traceback.extract_tb(tb)) 
    # process/modify lines 
    print(''.join(lines)) 

per ottenere il messaggio di errore traceback come una sequenza di linee, poi modificato e stampato come ti pare.


Ad esempio, se si desidera ridurre tutti i percorsi dei file di solo il suo nome base, è possibile utilizzare:

import sys 
import traceback 
import os 
import re 

def my_excepthook(type, value, tb): 
    lines = traceback.format_list(traceback.extract_tb(tb)) 
    def shorten(match): 
     return 'File "{}"'.format(os.path.basename(match.group(1))) 
    lines = [re.sub(r'File "([^"]+)"', shorten, line, 1) for line in lines] 
    print(''.join(lines)) 
    print('{}: {}'.format(type.__name__, value)) 

sys.excepthook = my_excepthook # comment this out to see the difference 

class Foo(): 
    def run(self): 
     1/0 

foo = Foo() 
foo.run() 

che produce

File "script.py", line 24, in <module> 
    foo.run() 
    File "script.py", line 21, in run 
    1/0 

ZeroDivisionError: division by zero 

invece di

Traceback (most recent call last): 
    File "/home/unutbu/pybin/script.py", line 24, in <module> 
    foo.run() 
    File "/home/unutbu/pybin/script.py", line 21, in run 
    1/0 
ZeroDivisionError: division by zero 
+1

Grazie, la sovrascrittura del metodo di sistema funziona perfettamente. Ho creato il mio modulo con il tuo codice. Quindi ho solo bisogno di una riga per importare questo modulo e non avere il sovraccarico del codice. Grande! – Jonas

0

Penso che il modo migliore per scrivere errori personalizzati è quello di utilizzare prova e tranne

try: 
    doSomething() # You code goes here. 
except Exception: 
    # Whatever you want to be shown, full path, anything. 
    pass 
0

Si può avere un blocco try except attorno al procedimento main o al livello più alto se non avere una routine main. Nel blocco except è possibile analizzare la traccia di eccezione per rimuovere il nome della directory e altre informazioni non importanti utilizzando il modulo traceback.

import traceback 
import sys 
if __name__ == '__main__': 
    try: 
     #SomeOperation 
     #More operation 
    except: 
     errorMsg = traceback.format_exc() 
     #Format error message according to your preference 
     print(errorMsgTransformed) 
     sys.exit(1)