コード例 #1
0
def get_exception_details():
    from traceback import walk_tb, StackSummary, FrameSummary
    from time import strftime
    cla, exc, exc_traceback = sys.exc_info()
    exc_args = exc.__dict__["args"] if "args" in exc.__dict__ else "<no args>"
    ex_title = cla.__name__ + ": Exception:" + str(exc) + " - args:" + str(
        exc_args)
    msgs = [
        ex_title,
    ]
    except_location = ""
    tb: list[FrameSummary] = StackSummary.extract(walk_tb(exc_traceback),
                                                  limit=None,
                                                  capture_locals=True)
    for frame in tb:
        local_vars_info = []
        if frame.locals:
            for name, value in frame.locals.items():
                if name == "self":
                    continue
                local_vars_info.append(f'\t{name} = {value}')
        except_location += "\n" + frame.filename + ":" + str(frame.lineno) + " \n" + str(frame.name) + \
                           "\n<Args>:" + "\n".join(local_vars_info)
    msgs.insert(1, except_location)
    time = strftime("%Y-%m-%d %H:%M:%S")
    return time + " - " + ("".join(msgs))
コード例 #2
0
def print_agen_stack(agen: AsyncGenerator,
                     *,
                     file: IO = sys.stderr,
                     limit: int = DEFAULT_MAX_FRAMES,
                     capture_locals: bool = False) -> None:
    """Print the stack trace for a currently running async generator."""
    print(f'Stack for {agen!r} (most recent call last):', file=file)
    tb = Traceback.from_agen(agen, limit=limit)
    print_list(
        StackSummary.extract(
            cast(Generator, walk_tb(cast(TracebackType, tb))),
            limit=limit,
            capture_locals=capture_locals,
        ),
        file=file,
    )
コード例 #3
0
def print_coro_stack(coro: Coroutine,
                     *,
                     file: IO = sys.stderr,
                     limit: int = DEFAULT_MAX_FRAMES,
                     capture_locals: bool = False) -> None:
    """Print the stack trace for a currently running coroutine."""
    print(f'Stack for {coro!r} (most recent call last):', file=file)
    tb = Traceback.from_coroutine(coro, limit=limit)
    print_list(
        StackSummary.extract(
            cast(Generator, walk_tb(cast(TracebackType, tb))),
            limit=limit,
            capture_locals=capture_locals,
        ),
        file=file,
    )
コード例 #4
0
def print_task_stack(task: asyncio.Task,
                     *,
                     file: IO = sys.stderr,
                     limit: int = DEFAULT_MAX_FRAMES,
                     capture_locals: bool = False) -> None:
    """Print the stack trace for an :class:`asyncio.Task`."""
    print(f'Stack for {task!r} (most recent call last):', file=file)
    tb = Traceback.from_task(task, limit=limit)
    print_list(
        StackSummary.extract(
            cast(Generator, walk_tb(cast(TracebackType, tb))),
            limit=limit,
            capture_locals=capture_locals,
        ),
        file=file,
    )
コード例 #5
0
def extract_log_tb(exc=None):
    tb = ''.join(StackSummary.extract(walk_tb(sys.exc_info()[-1])).format())
    if exc.__cause__ is not None and isinstance(exc.__cause__, Traceback):
        tb = exc.__cause__.tb + tb
    return tb
コード例 #6
0
ファイル: inspector.py プロジェクト: Dragon2fly/logger_tt
def analyze_frame(trace_back, full_context: int = False) -> str:
    """
    Read out variables' content surrounding the error line of code

    :param trace_back: A traceback object when exception occur
    :param full_context: Also export local variables that is not in the error line
            full_context == 0: export only variables that appear on the error line
            full_context == 1: export variables within the error function's scope
            full_context >= 2: export variables along the function's call stack up to `full_context` level
    :return: string of analyzed frame
    """
    result = []
    full_context = max(0, int(full_context))
    # todo: add color
    bullet_1 = '|->'
    bullet_2 = '=>'
    multi_line_indent1 = 8 + len(bullet_1)
    multi_line_indent2 = 8 + len(bullet_2)
    stack_depth = get_traceback_depth(trace_back)

    with logging_disabled():
        for idx, obj in enumerate(walk_tb(trace_back)):
            frame, _ = obj

            global_var = frame.f_globals
            local_var = frame.f_locals

            summary = StackSummary.extract([obj], capture_locals=True)[0]
            line = summary.line
            if not is_full_statement(summary.line):
                line = get_full_statement(summary.filename, summary.lineno)
                line = '    '.join(line)

            txt = [
                f'  File "{summary.filename}", line {summary.lineno}, in {summary.name}',
                f'    {line}'
            ]

            # todo: dump all level to different file?
            parse_level = max(full_context - 1, 0)
            if idx + 1 < (stack_depth - parse_level):
                # don't parse variables for top levels
                txt.append('')
                result.append('\n'.join(txt))
                continue

            # get value of variables on the error line
            identifiers = ID_PATTERN.findall(line)
            seen = set()
            outer = "(outer) " if idx else ""  # ground level variables are not outer for sure
            for i in identifiers:
                if i in seen or i.endswith('.'):
                    continue

                seen.add(i)
                spaces = multi_line_indent1 + len(i)
                if i in local_var:
                    value = get_repr(local_var[i], spaces)
                    txt.append(f'     {bullet_1} {i} = {value}')
                elif i in global_var:
                    spaces += len(outer)
                    value = get_repr(global_var[i], spaces)
                    txt.append(f'     {bullet_1} {outer}{i} = {value}')
                elif '.' in i:
                    # class attribute access
                    spaces += len(outer)
                    instance = i.split('.')[0]
                    obj = local_var.get(instance, global_var.get(instance))
                    attribute = get_recur_attr(obj, i[len(instance) + 1:])
                    value = get_repr(attribute, spaces)
                    scope = outer if instance in global_var else ''
                    txt.append(f'     {bullet_1} {scope}{i} = {value}')
                else:
                    # reserved Keyword or non-identifier, eg. word inside the string
                    pass

            # get value of other variables within local scope
            if full_context:
                other_local_var = set(local_var) - set(identifiers)
                if other_local_var:
                    spaces = multi_line_indent2
                    txt.extend([
                        f'     {bullet_2} {k} = {get_repr(v, spaces + len(k))}'
                        for k, v in local_var.items() if k in other_local_var
                    ])

            txt.append('')
            result.append('\n'.join(txt))

    return '\n'.join(result)