Cetak tumpukan panggilan saat ini dari metode dalam kode Python

276

Dalam Python, bagaimana saya bisa mencetak tumpukan panggilan saat ini dari dalam suatu metode (untuk tujuan debugging).

diri
sumber

Jawaban:

319

Berikut adalah contoh mendapatkan tumpukan melalui modul traceback , dan mencetaknya:

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

Jika Anda benar-benar hanya ingin mencetak tumpukan ke stderr, Anda dapat menggunakan:

traceback.print_stack()

Atau untuk mencetak ke stdout (berguna jika ingin menyimpan hasil yang dialihkan bersamaan), gunakan:

traceback.print_stack(file=sys.stdout)

Tetapi mendapatkannya melalui traceback.format_stack()memungkinkan Anda melakukan apa pun yang Anda suka dengannya.

RichieHindle
sumber
Bagaimana melakukan hal yang sama untuk semua utas lainnya (saya berbicara tentang utas yang tidak saya kendalikan)  ?
user2284570
Mungkin saya kehilangan sesuatu di sini, tetapi Anda memanggil f yang hanya tujuan di sini adalah untuk memanggil g dan tidak melakukan hal lain. Mengapa
Chris
6
@ Chris: Ini hanya sebuah contoh. Ini memiliki beberapa fungsi untuk menjelaskan bahwa format_stack () mencetak semua panggilan pada stack.
RichieHindle
Jika Anda ingin mendapatkan lebih banyak keluaran verbose (termasuk vars dll), lihat pertanyaan terkait ini , dan yang ini .
Albert
@ user2284570: Anda bisa menggunakan sys._current_frames(). Misalnya py_better_exchookdump_all_thread_tracebacks melakukan itu (penafian: saya menulis itu).
Albert,
93
import traceback
traceback.print_stack()
Mark Roddy
sumber
8
Sebenarnya, saya suka traceback.print_exc()yang memberi Anda hal yang hampir sama dengan yang Anda dapatkan tanpa exceptpernyataan (dan juga lebih sedikit coding daripada jawaban yang diterima).
martineau
34
traceback.print_exc()mencetak jejak tumpukan untuk pengecualian apa pun yang mungkin Anda tangani - tetapi ini tidak menyelesaikan pertanyaan awal, yaitu bagaimana cara mencetak tumpukan saat ini ("di mana Anda sekarang" sebagai lawan "di mana kode Anda berada saat pengecualian terakhir terjadi off, jika ada ".)
Tom Swirly
17

Jika Anda menggunakan python debugger, tidak hanya variabel interaktif penyelidikan tetapi Anda bisa mendapatkan tumpukan panggilan dengan perintah "where" atau "w".

Jadi di bagian atas program Anda

import pdb

Kemudian dalam kode tempat Anda ingin melihat apa yang terjadi

pdb.set_trace()

dan Anda masuk ke prompt

Keir
sumber
2
Saya sudah pemrograman dengan Python selama lebih dari satu dekade. Ada begitu banyak kali saya bisa menggunakan ini! Saya tidak percaya saya baru tahu tentang itu.
hosford42
1
Bagaimana hubungannya dengan ini where?
skia.heliou
4
Untuk menjawab bagian "di mana" dari pertanyaan: Setelah Anda mendapatkan prompt pdb (pdb) ketik saja wheredan itu akan mencetak jejak tumpukan ke terminal.
stephenmm
1
Python 3.7 dan di atasnya memiliki fungsi builtin breakpoint()yang meniadakan kebutuhan untuk mengimpor pdb.
user650654
6

bagi mereka yang perlu mencetak tumpukan panggilan saat menggunakan pdb, lakukan saja

(Pdb) where
mouserat
sumber
2

Berikut variasi jawaban istimewa dari RichieHindle yang mengimplementasikan dekorator yang dapat diterapkan secara selektif ke fungsi yang diinginkan. Bekerja dengan Python 2.7.14 dan 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())

Output dari sampel:

test_func() called:
    File "stacktrace_decorator.py", line 28, in <module>
    print(test_func())
42
martineau
sumber
Menulis versi dekorator saya sendiri sebelum saya melihat ini. Terpilih.
Sida Zhou
0

Instal Inspect-it

pip3 install inspect-it --user

Kode

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

Anda dapat membuat cuplikan dari baris ini

itu akan menunjukkan kepada Anda daftar tumpukan panggilan fungsi dengan nama file dan nomor baris

daftar dari awal ke tempat Anda meletakkan baris ini

MohitGhodasara
sumber