web-dev-qa-db-fra.com

Imprimer la pile d'appels en cours à partir d'une méthode en code Python

En Python, comment puis-je imprimer la pile d'appels en cours à partir d'une méthode (à des fins de débogage).

220
oneself

Voici un exemple d'obtention de la pile via le module traceback et de son impression:

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 vous voulez uniquement imprimer la pile sur stderr, vous pouvez utiliser:

traceback.print_stack()

Ou pour imprimer sur la sortie standard (utile si vous souhaitez conserver la sortie redirigée ensemble), utilisez:

traceback.print_stack(file=sys.stdout)

Mais l'obtenir via traceback.format_stack() vous permet de faire ce que vous voulez.

250
RichieHindle
import traceback
traceback.print_stack()
77
Mark Roddy

inspect.stack() renvoie la pile actuelle plutôt que l'exception traceback:

import inspect
print inspect.stack()

Voir https://Gist.github.com/FredLoney/5454553 pour une fonction utilitaire log_stack.

27
Fred Loney

Si vous utilisez le débogueur Python, non seulement une analyse interactive des variables mais vous pouvez obtenir la pile d'appels avec la commande "where" ou "w".

Donc au sommet de votre programme

import pdb

Puis dans le code où vous voulez voir ce qui se passe

pdb.set_trace()

et vous êtes tombé dans une invite

9
Keir

Installer Inspect-it

pip3 install inspect-it --user

Code

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()])

vous pouvez faire un extrait de cette ligne

il vous montrera une liste de pile d'appels de fonction avec un nom de fichier et un numéro de ligne

liste du début à l'endroit où vous mettez cette ligne

1
MohitGhodasara

Voici une variante de l'excellente réponse de @ RichieHindle qui implémente un décorateur qui peut être appliqué de manière sélective aux fonctions à votre guise. Fonctionne avec Python 2.7.14 et 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())

Sortie de l'échantillon:

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