Back to index

python3.2  3.2.2
traceback.py
Go to the documentation of this file.
00001 """Extract, format and print information about Python stack traces."""
00002 
00003 import linecache
00004 import sys
00005 
00006 __all__ = ['extract_stack', 'extract_tb', 'format_exception',
00007            'format_exception_only', 'format_list', 'format_stack',
00008            'format_tb', 'print_exc', 'format_exc', 'print_exception',
00009            'print_last', 'print_stack', 'print_tb']
00010 
00011 def _print(file, str='', terminator='\n'):
00012     file.write(str+terminator)
00013 
00014 
00015 def print_list(extracted_list, file=None):
00016     """Print the list of tuples as returned by extract_tb() or
00017     extract_stack() as a formatted stack trace to the given file."""
00018     if file is None:
00019         file = sys.stderr
00020     for filename, lineno, name, line in extracted_list:
00021         _print(file,
00022                '  File "%s", line %d, in %s' % (filename,lineno,name))
00023         if line:
00024             _print(file, '    %s' % line.strip())
00025 
00026 def format_list(extracted_list):
00027     """Format a list of traceback entry tuples for printing.
00028 
00029     Given a list of tuples as returned by extract_tb() or
00030     extract_stack(), return a list of strings ready for printing.
00031     Each string in the resulting list corresponds to the item with the
00032     same index in the argument list.  Each string ends in a newline;
00033     the strings may contain internal newlines as well, for those items
00034     whose source text line is not None.
00035     """
00036     list = []
00037     for filename, lineno, name, line in extracted_list:
00038         item = '  File "%s", line %d, in %s\n' % (filename,lineno,name)
00039         if line:
00040             item = item + '    %s\n' % line.strip()
00041         list.append(item)
00042     return list
00043 
00044 
00045 def print_tb(tb, limit=None, file=None):
00046     """Print up to 'limit' stack trace entries from the traceback 'tb'.
00047 
00048     If 'limit' is omitted or None, all entries are printed.  If 'file'
00049     is omitted or None, the output goes to sys.stderr; otherwise
00050     'file' should be an open file or file-like object with a write()
00051     method.
00052     """
00053     if file is None:
00054         file = sys.stderr
00055     if limit is None:
00056         if hasattr(sys, 'tracebacklimit'):
00057             limit = sys.tracebacklimit
00058     n = 0
00059     while tb is not None and (limit is None or n < limit):
00060         f = tb.tb_frame
00061         lineno = tb.tb_lineno
00062         co = f.f_code
00063         filename = co.co_filename
00064         name = co.co_name
00065         _print(file,
00066                '  File "%s", line %d, in %s' % (filename, lineno, name))
00067         linecache.checkcache(filename)
00068         line = linecache.getline(filename, lineno, f.f_globals)
00069         if line: _print(file, '    ' + line.strip())
00070         tb = tb.tb_next
00071         n = n+1
00072 
00073 def format_tb(tb, limit=None):
00074     """A shorthand for 'format_list(extract_stack(f, limit))."""
00075     return format_list(extract_tb(tb, limit))
00076 
00077 def extract_tb(tb, limit=None):
00078     """Return list of up to limit pre-processed entries from traceback.
00079 
00080     This is useful for alternate formatting of stack traces.  If
00081     'limit' is omitted or None, all entries are extracted.  A
00082     pre-processed stack trace entry is a quadruple (filename, line
00083     number, function name, text) representing the information that is
00084     usually printed for a stack trace.  The text is a string with
00085     leading and trailing whitespace stripped; if the source is not
00086     available it is None.
00087     """
00088     if limit is None:
00089         if hasattr(sys, 'tracebacklimit'):
00090             limit = sys.tracebacklimit
00091     list = []
00092     n = 0
00093     while tb is not None and (limit is None or n < limit):
00094         f = tb.tb_frame
00095         lineno = tb.tb_lineno
00096         co = f.f_code
00097         filename = co.co_filename
00098         name = co.co_name
00099         linecache.checkcache(filename)
00100         line = linecache.getline(filename, lineno, f.f_globals)
00101         if line: line = line.strip()
00102         else: line = None
00103         list.append((filename, lineno, name, line))
00104         tb = tb.tb_next
00105         n = n+1
00106     return list
00107 
00108 
00109 _cause_message = (
00110     "\nThe above exception was the direct cause "
00111     "of the following exception:\n")
00112 
00113 _context_message = (
00114     "\nDuring handling of the above exception, "
00115     "another exception occurred:\n")
00116 
00117 def _iter_chain(exc, custom_tb=None, seen=None):
00118     if seen is None:
00119         seen = set()
00120     seen.add(exc)
00121     its = []
00122     cause = exc.__cause__
00123     if cause is not None and cause not in seen:
00124         its.append(_iter_chain(cause, None, seen))
00125         its.append([(_cause_message, None)])
00126     else:
00127         context = exc.__context__
00128         if context is not None and context not in seen:
00129             its.append(_iter_chain(context, None, seen))
00130             its.append([(_context_message, None)])
00131     its.append([(exc, custom_tb or exc.__traceback__)])
00132     # itertools.chain is in an extension module and may be unavailable
00133     for it in its:
00134         for x in it:
00135             yield x
00136 
00137 
00138 def print_exception(etype, value, tb, limit=None, file=None, chain=True):
00139     """Print exception up to 'limit' stack trace entries from 'tb' to 'file'.
00140 
00141     This differs from print_tb() in the following ways: (1) if
00142     traceback is not None, it prints a header "Traceback (most recent
00143     call last):"; (2) it prints the exception type and value after the
00144     stack trace; (3) if type is SyntaxError and value has the
00145     appropriate format, it prints the line where the syntax error
00146     occurred with a caret on the next line indicating the approximate
00147     position of the error.
00148     """
00149     if file is None:
00150         file = sys.stderr
00151     if chain:
00152         values = _iter_chain(value, tb)
00153     else:
00154         values = [(value, tb)]
00155     for value, tb in values:
00156         if isinstance(value, str):
00157             _print(file, value)
00158             continue
00159         if tb:
00160             _print(file, 'Traceback (most recent call last):')
00161             print_tb(tb, limit, file)
00162         lines = format_exception_only(type(value), value)
00163         for line in lines:
00164             _print(file, line, '')
00165 
00166 def format_exception(etype, value, tb, limit=None, chain=True):
00167     """Format a stack trace and the exception information.
00168 
00169     The arguments have the same meaning as the corresponding arguments
00170     to print_exception().  The return value is a list of strings, each
00171     ending in a newline and some containing internal newlines.  When
00172     these lines are concatenated and printed, exactly the same text is
00173     printed as does print_exception().
00174     """
00175     list = []
00176     if chain:
00177         values = _iter_chain(value, tb)
00178     else:
00179         values = [(value, tb)]
00180     for value, tb in values:
00181         if isinstance(value, str):
00182             list.append(value + '\n')
00183             continue
00184         if tb:
00185             list.append('Traceback (most recent call last):\n')
00186             list.extend(format_tb(tb, limit))
00187         list.extend(format_exception_only(type(value), value))
00188     return list
00189 
00190 def format_exception_only(etype, value):
00191     """Format the exception part of a traceback.
00192 
00193     The arguments are the exception type and value such as given by
00194     sys.last_type and sys.last_value. The return value is a list of
00195     strings, each ending in a newline.
00196 
00197     Normally, the list contains a single string; however, for
00198     SyntaxError exceptions, it contains several lines that (when
00199     printed) display detailed information about where the syntax
00200     error occurred.
00201 
00202     The message indicating which exception occurred is always the last
00203     string in the list.
00204 
00205     """
00206     # Gracefully handle (the way Python 2.4 and earlier did) the case of
00207     # being called with (None, None).
00208     if etype is None:
00209         return [_format_final_exc_line(etype, value)]
00210 
00211     stype = etype.__name__
00212     smod = etype.__module__
00213     if smod not in ("__main__", "builtins"):
00214         stype = smod + '.' + stype
00215 
00216     if not issubclass(etype, SyntaxError):
00217         return [_format_final_exc_line(stype, value)]
00218 
00219     # It was a syntax error; show exactly where the problem was found.
00220     lines = []
00221     filename = value.filename or "<string>"
00222     lineno = str(value.lineno) or '?'
00223     lines.append('  File "%s", line %s\n' % (filename, lineno))
00224     badline = value.text
00225     offset = value.offset
00226     if badline is not None:
00227         lines.append('    %s\n' % badline.strip())
00228         if offset is not None:
00229             caretspace = badline.rstrip('\n')[:offset].lstrip()
00230             # non-space whitespace (likes tabs) must be kept for alignment
00231             caretspace = ((c.isspace() and c or ' ') for c in caretspace)
00232             # only three spaces to account for offset1 == pos 0
00233             lines.append('   %s^\n' % ''.join(caretspace))
00234     msg = value.msg or "<no detail available>"
00235     lines.append("%s: %s\n" % (stype, msg))
00236     return lines
00237 
00238 def _format_final_exc_line(etype, value):
00239     valuestr = _some_str(value)
00240     if value is None or not valuestr:
00241         line = "%s\n" % etype
00242     else:
00243         line = "%s: %s\n" % (etype, valuestr)
00244     return line
00245 
00246 def _some_str(value):
00247     try:
00248         return str(value)
00249     except:
00250         return '<unprintable %s object>' % type(value).__name__
00251 
00252 
00253 def print_exc(limit=None, file=None, chain=True):
00254     """Shorthand for 'print_exception(*sys.exc_info(), limit, file)'."""
00255     if file is None:
00256         file = sys.stderr
00257     try:
00258         etype, value, tb = sys.exc_info()
00259         print_exception(etype, value, tb, limit, file, chain)
00260     finally:
00261         etype = value = tb = None
00262 
00263 
00264 def format_exc(limit=None, chain=True):
00265     """Like print_exc() but return a string."""
00266     try:
00267         etype, value, tb = sys.exc_info()
00268         return ''.join(
00269             format_exception(etype, value, tb, limit, chain))
00270     finally:
00271         etype = value = tb = None
00272 
00273 
00274 def print_last(limit=None, file=None, chain=True):
00275     """This is a shorthand for 'print_exception(sys.last_type,
00276     sys.last_value, sys.last_traceback, limit, file)'."""
00277     if not hasattr(sys, "last_type"):
00278         raise ValueError("no last exception")
00279     if file is None:
00280         file = sys.stderr
00281     print_exception(sys.last_type, sys.last_value, sys.last_traceback,
00282                     limit, file, chain)
00283 
00284 
00285 def print_stack(f=None, limit=None, file=None):
00286     """Print a stack trace from its invocation point.
00287 
00288     The optional 'f' argument can be used to specify an alternate
00289     stack frame at which to start. The optional 'limit' and 'file'
00290     arguments have the same meaning as for print_exception().
00291     """
00292     if f is None:
00293         try:
00294             raise ZeroDivisionError
00295         except ZeroDivisionError:
00296             f = sys.exc_info()[2].tb_frame.f_back
00297     print_list(extract_stack(f, limit), file)
00298 
00299 def format_stack(f=None, limit=None):
00300     """Shorthand for 'format_list(extract_stack(f, limit))'."""
00301     if f is None:
00302         try:
00303             raise ZeroDivisionError
00304         except ZeroDivisionError:
00305             f = sys.exc_info()[2].tb_frame.f_back
00306     return format_list(extract_stack(f, limit))
00307 
00308 def extract_stack(f=None, limit=None):
00309     """Extract the raw traceback from the current stack frame.
00310 
00311     The return value has the same format as for extract_tb().  The
00312     optional 'f' and 'limit' arguments have the same meaning as for
00313     print_stack().  Each item in the list is a quadruple (filename,
00314     line number, function name, text), and the entries are in order
00315     from oldest to newest stack frame.
00316     """
00317     if f is None:
00318         try:
00319             raise ZeroDivisionError
00320         except ZeroDivisionError:
00321             f = sys.exc_info()[2].tb_frame.f_back
00322     if limit is None:
00323         if hasattr(sys, 'tracebacklimit'):
00324             limit = sys.tracebacklimit
00325     list = []
00326     n = 0
00327     while f is not None and (limit is None or n < limit):
00328         lineno = f.f_lineno
00329         co = f.f_code
00330         filename = co.co_filename
00331         name = co.co_name
00332         linecache.checkcache(filename)
00333         line = linecache.getline(filename, lineno, f.f_globals)
00334         if line: line = line.strip()
00335         else: line = None
00336         list.append((filename, lineno, name, line))
00337         f = f.f_back
00338         n = n+1
00339     list.reverse()
00340     return list