|
| 1 | +import sys |
| 2 | +import traceback |
| 3 | + |
| 4 | + |
| 5 | +def get_stacktrace(limit=None): |
| 6 | + """ |
| 7 | + Get a full stacktrace for the current state of execution. |
| 8 | +
|
| 9 | + Include the current state of the stack, minus this function. |
| 10 | + If there is an active exception, include the stacktrace information from |
| 11 | + the exception as well. |
| 12 | +
|
| 13 | + :param int limit: |
| 14 | + Optionally limit stack trace size results. This parmaeters has the same |
| 15 | + meaning as the `limit` parameter in `traceback.print_stack`. |
| 16 | + :returns: |
| 17 | + List of stack trace objects, in the same form as |
| 18 | + `traceback.extract_stack`. |
| 19 | + """ |
| 20 | + if limit is not None and limit == 0: |
| 21 | + # Nothing to return. This is consistent with the behavior of the |
| 22 | + # functions in the `traceback` module. |
| 23 | + return [] |
| 24 | + |
| 25 | + stack = traceback.extract_stack() |
| 26 | + # Remove this `get_stacktrace()` function call from the stack info. |
| 27 | + # For what we want to report, this is superfluous information and arguably |
| 28 | + # adds garbage to the report. |
| 29 | + # Also drop the `traceback.extract_stack()` call above from the returned |
| 30 | + # stack info, since this is also superfluous. |
| 31 | + stack = stack[:-2] |
| 32 | + |
| 33 | + _exc_type, _exc, exc_traceback = sys.exc_info() |
| 34 | + if exc_traceback is not None: |
| 35 | + # If and only if there is a currently triggered exception, combine the |
| 36 | + # exception traceback information with the current stack state to get a |
| 37 | + # complete trace. |
| 38 | + exc_stack = traceback.extract_tb(exc_traceback) |
| 39 | + stack += exc_stack |
| 40 | + |
| 41 | + # Limit the stack trace size, if a limit was specified: |
| 42 | + if limit is not None: |
| 43 | + # Copy the behavior of `traceback` functions with a `limit` argument. |
| 44 | + # See https://docs.python.org/3/library/traceback.html. |
| 45 | + if limit > 0: |
| 46 | + # limit > 0: include the last `limit` items |
| 47 | + stack = stack[-limit:] |
| 48 | + else: |
| 49 | + # limit < 0: include the first `abs(limit)` items |
| 50 | + stack = stack[:abs(limit)] |
| 51 | + return stack |
0 commit comments