Imprime la pila de llamadas actual desde un método en código Python


Respuestas:


319

Aquí hay un ejemplo de cómo obtener la pila a través del módulo de rastreo e imprimirla:

import traceback

def f():
    g()

def g():
    for line in traceback.format_stack():
        print(line.strip())

f()

# Prints:
# File "so-stack.py", line 10, in <module>
#     f()
# File "so-stack.py", line 4, in f
#     g()
# File "so-stack.py", line 7, in g
#     for line in traceback.format_stack():

Si realmente solo desea imprimir la pila en stderr, puede usar:

traceback.print_stack()

O para imprimir en stdout (útil si desea mantener juntos la salida redirigida), use:

traceback.print_stack(file=sys.stdout)

Pero conseguirlo te traceback.format_stack()permite hacer lo que quieras con él.


¿Cómo hacer lo mismo para todos los otros hilos (estoy hablando de hilos que no controlo)  ?
usuario2284570

Tal vez me estoy perdiendo algo aquí, pero llamas a f, cuyo único propósito es llamar a gy no hace nada más. ¿Por qué
Chris

66
@ Chris: Es solo un ejemplo. Tiene múltiples funciones para dejar en claro que format_stack () imprime todas las llamadas en la pila.
RichieHindle

Si desea obtener un resultado más detallado (incluidos vars, etc.), consulte esta pregunta relacionada y esta .
Albert

@ usuario2284570: puede usar sys._current_frames(). Por ejemplo, py_better_exchookdump_all_thread_tracebacks hace eso (descargo de responsabilidad: escribí eso).
Albert

93
import traceback
traceback.print_stack()

8
En realidad, me gusta lo traceback.print_exc()que te da casi lo mismo que hubieras obtenido sin la exceptdeclaración (y también es menos codificado que la respuesta aceptada).
Martineau el

34
traceback.print_exc()imprime el seguimiento de la pila para cualquier excepción que pueda estar manejando, pero esto no resuelve la pregunta original, que es cómo imprimir la pila actual ("dónde está ahora" en lugar de "dónde estaba su código cuando se produjo la última excepción off, if any ".)
Tom Swirly


17

Si usa el depurador de python, no solo sondea interactivamente las variables, sino que puede obtener la pila de llamadas con el comando "where" o "w".

Así que en la parte superior de tu programa

import pdb

Luego en el código donde quieres ver lo que está sucediendo

pdb.set_trace()

y te dejan caer en un aviso


2
He estado programando en Python por más de una década. Hay así que muchas veces que podría haber utilizado este! No puedo creer que ahora me estoy enterando.
hosford42

1
¿Cómo se relaciona esto where?
skia.heliou

44
Para responder la parte "dónde" de la pregunta: Después de obtener el indicador pdb, (pdb) simplemente escriba wheree imprimirá el seguimiento de la pila en el terminal.
stephenmm

1
Python 3.7 y superior tienen una función incorporada breakpoint()que evita la necesidad de importar pdb.
user650654

6

para aquellos que necesitan imprimir la pila de llamadas mientras usan pdb, simplemente hagan

(Pdb) where

2

Aquí hay una variación de la excelente respuesta de @ RichieHindle que implementa un decorador que se puede aplicar selectivamente a las funciones según lo desee. Funciona con Python 2.7.14 y 3.6.4.

from __future__ import print_function
import functools
import traceback
import sys

INDENT = 4*' '

def stacktrace(func):
    @functools.wraps(func)
    def wrapped(*args, **kwds):
        # Get all but last line returned by traceback.format_stack()
        # which is the line below.
        callstack = '\n'.join([INDENT+line.strip() for line in traceback.format_stack()][:-1])
        print('{}() called:'.format(func.__name__))
        print(callstack)
        return func(*args, **kwds)

    return wrapped

@stacktrace
def test_func():
    return 42

print(test_func())

Salida de muestra:

test_func() called:
    File "stacktrace_decorator.py", line 28, in <module>
    print(test_func())
42

Escribí mi propia versión de decorador antes de ver esto. Votado
Sida Zhou

0

Instalar Inspect-it

pip3 install inspect-it --user

Código

import inspect;print(*['\n\x1b[0;36;1m| \x1b[0;32;1m{:25}\x1b[0;36;1m| \x1b[0;35;1m{}'.format(str(x.function), x.filename+'\x1b[0;31;1m:'+str(x.lineno)+'\x1b[0m') for x in inspect.stack()])

puedes hacer un fragmento de esta línea

le mostrará una lista de la pila de llamadas de función con un nombre de archivo y un número de línea

lista desde el principio hasta donde pones esta línea

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.