พิมพ์ call stack ปัจจุบันจากวิธีการในรหัส Python


คำตอบ:


319

นี่คือตัวอย่างของการรับสแต็กผ่านโมดูลtracebackและพิมพ์:

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

หากคุณต้องการพิมพ์สแต็กเป็น stderr จริงๆคุณสามารถใช้:

traceback.print_stack()

หรือหากต้องการพิมพ์ไปยัง stdout (มีประโยชน์หากต้องการเก็บเอาท์พุทที่เปลี่ยนเส้นทางไปด้วยกัน) ให้ใช้:

traceback.print_stack(file=sys.stdout)

แต่การรับมันผ่านtraceback.format_stack()ช่วยให้คุณทำสิ่งที่คุณชอบด้วย


วิธีการทำเช่นเดียวกันสำหรับหัวข้ออื่น ๆ ทั้งหมด(ฉันพูดคุยเกี่ยวกับหัวข้อฉันไม่ควบคุม)  ?
2284570

บางทีฉันอาจจะพลาดบางสิ่งบางอย่างที่นี่ แต่คุณเรียกว่า f ซึ่งมีจุดประสงค์เพียงอย่างเดียวคือที่นี่เพื่อโทรหา g และไม่ทำอะไรเลย ทำไม
Chris

6
@Chris: มันเป็นเพียงตัวอย่าง มันมีฟังก์ชั่นหลายอย่างที่ทำให้ชัดเจนว่า format_stack () พิมพ์การโทรทั้งหมดบนสแต็ก
RichieHindle

หากคุณต้องการที่จะได้รับเพิ่มเติมบางอย่างละเอียดเอาท์พุท (รวม vars ฯลฯ ) เห็นนี้คำถามที่เกี่ยวข้องและคนนี้
อัลเบิร์

@ user2284570: คุณสามารถsys._current_frames()ใช้ได้ เช่นpy_better_exchookdump_all_thread_tracebacksทำเช่นนั้น (ข้อจำกัดความรับผิดชอบ: ฉันเขียนไว้)
อัลเบิร์

93
import traceback
traceback.print_stack()

8
ที่จริงแล้วฉันชอบtraceback.print_exc()ที่ให้คุณเกือบเหมือนกันกับที่คุณจะได้รับโดยไม่ต้องมีexceptคำสั่ง (และยังมีการเข้ารหัสน้อยกว่าคำตอบที่ยอมรับ)
martineau

34
traceback.print_exc()พิมพ์การติดตามสแต็กสำหรับข้อยกเว้นใด ๆ ที่คุณอาจกำลังจัดการ - แต่นี่ไม่ได้แก้ปัญหาเดิมซึ่งเป็นวิธีการพิมพ์สแต็กปัจจุบัน ("ที่ที่คุณอยู่ในขณะนี้" ซึ่งตรงข้ามกับ ปิดถ้ามี ".)
Tom Swirly


17

หากคุณใช้ python debugger ไม่เพียง แต่การตรวจสอบตัวแปรแบบโต้ตอบเท่านั้น แต่คุณสามารถรับ call stack ด้วยคำสั่ง "where" หรือ "w"

ดังนั้นที่ด้านบนสุดของโปรแกรมของคุณ

import pdb

จากนั้นในรหัสที่คุณต้องการดูสิ่งที่เกิดขึ้น

pdb.set_trace()

และคุณได้รับพร้อมท์


2
ฉันเขียนโปรแกรมใน Python มานานกว่าทศวรรษแล้ว นอกจากนี้เพื่อให้หลายครั้งฉันจะได้ใช้นี้! ฉันไม่อยากจะเชื่อเลยว่าตอนนี้ฉันรู้แล้ว
hosford42

1
สิ่งนี้เกี่ยวข้องกับwhereอย่างไร
skia.heliou

4
ในการตอบคำถาม "ที่ไหน" ส่วนหนึ่งของคำถาม: หลังจากที่คุณได้รับพรอมต์ pdb (pdb) เพียงพิมพ์whereแล้วมันจะพิมพ์สแต็กติดตามไปยังเทอร์มินัล
stephenmm

1
Python 3.7 และสูงกว่านั้นมีฟังก์ชั่นbreakpoint()บิวอินซึ่ง obviates จำเป็นต้องนำเข้า pdb
user650654


2

นี่คือรูปแบบของคำตอบที่ยอดเยี่ยมของ @ RichieHindle ซึ่งใช้เครื่องมือตกแต่งที่สามารถเลือกใช้กับฟังก์ชั่นได้ตามต้องการ ทำงานร่วมกับ Python 2.7.14 และ 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())

ผลลัพธ์จากตัวอย่าง:

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

เขียนเวอร์ชันมัณฑนากรของฉันเองก่อนที่ฉันจะเห็นสิ่งนี้ upvoted
สีดาโจว

0

ติดตั้งInspect-it

pip3 install inspect-it --user

รหัส

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

คุณสามารถสร้างตัวอย่างของบรรทัดนี้

มันจะแสดงรายการสแตกการเรียกใช้ฟังก์ชันพร้อมชื่อไฟล์และหมายเลขบรรทัด

รายการตั้งแต่ต้นจนถึงที่คุณใส่บรรทัดนี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.