ukotvit menu |
Tohle je poměrně užitečná ukázka vylepšeného chybového hlášení k zachycené výjimce. Lze vypsa na obrazovku, uložit do logu nebo databáze, ze serveru poslat klientovi a podobně. Uživatel to asi příliš neocení, ale pro programátora je to výborná pomůcka při ladění programu.
Najzajímavější na tom bude asi:
demefrex.py - 3 182 B (debug message from exception)
Traceback (most recent call last): File "u_trace.py", line 119, in ? first() File "u_trace.py", line 101, in first first_in(1, 0) File "u_trace.py", line 97, in first_in d = a/b ZeroDivisionError: integer division or modulo by zero
====================================================================== EXCEPTION: exceptions.ZeroDivisionError ERROR MSG: integer division or modulo by zero TRACE: u_trace.py/109 main: first() u_trace.py/101 first: first_in(1, 0) u_trace.py/97 first_in: d = a/b CODE: 93 def first_in(a, b): 94 ''' Testovaci funkce kde dojde k vyjimce. ''' 95 96 c = ['q', 123, None] 97 d = a/b LOCAL VARS: a = (<type 'int'>) 1 b = (<type 'int'>) 0 c = (<type 'list'>) ['q', 123, None] ----------------------------------------------------------------------
# encoding: utf-8 import sys, inspect, pprint MAX_STRLEN_VALUE = 60 MIN_CODE_LINES = 10 def getTextFromCode(code, offset, linenu): ''' Print relevant part source code. ''' code = code[:offset+1] code.reverse() shortCode = [] for i, line in enumerate(code): sLine = line.strip() if sLine[:3] == 'def': shortCode.insert(0, line) break if sLine[:5] == 'class': shortCode.insert(0, line) break if sLine == '' and i > MIN_CODE_LINES: break shortCode.insert(0, line) offset = len(shortCode)-1 TEXT = [] for i, line in enumerate(shortCode): number = linenu-offset+i line = line[:-1] TEXT.append("%5d %s" % (number, line)) return '\n'.join(TEXT) def getTextFromDict(d, title=None): ''' Pretty print of dict. ''' TEXT = [] if title: TEXT.append(title) keys = d.keys() keys.sort() keyMaxLen = 0 for key in keys: if len(key) > keyMaxLen: keyMaxLen = len(key) keyMaxLen += 3 pattern = '%%%ds = (%%s) %%s' % keyMaxLen for key in keys: TEXT.append(pattern % (key, type(d[key]), str(d[key])[:MAX_STRLEN_VALUE])) return '\n'.join(TEXT) def makeTextFromException(size='full'): ''' Make information about exception. ''' TEXT = [] typerr,strerr,c = sys.exc_info() TEXT.append('\n==================================================================') TEXT.append('EXCEPTION: ' + str(typerr)) TEXT.append('TRACE: ') traceback = inspect.trace(100) last = len(traceback) - 1 for i, (frame, file, linenu, object, code, offset) in enumerate(traceback): if code and code[offset]: example = code[offset].strip() else: example = '<N/A>' if size == 'full' or i == last: TEXT.append(' %s/%d %s: %s' % (file, linenu, object, example)) if(i == last): if code and size == 'full': TEXT.append('CODE: ') TEXT.append(getTextFromCode(code, offset, linenu)) TEXT.insert(2, 'ERROR MSG: ' + str(strerr)) if size == 'full': TEXT.append(getTextFromDict(frame.f_locals, 'LOCAL VARS:')) TEXT.append('------------------------------------------------------------------') return '\n'.join(TEXT) ## SELF TEST ############################################## if __name__ == "__main__": class MyError(Exception): def __init__(self, value): self.value = value def __str__(self): return str(self.value) def first_in(a, b): ''' Testovaci funkce kde dojde k vyjimce. ''' c = ['q', 123, None] d = a/b def first(): ''' Testovaci funkce. ''' first_in(1, 0) def second(): raise MyError("můj error") def main(): ''' Self test. ''' try: first() except: print makeTextFromException() try: second() except: print makeTextFromException() main()