2 回答

TA貢獻1811條經(jīng)驗 獲得超6個贊
我認為,使用堆棧跟蹤,您正在尋找錯誤的地方。當您print_stack從一個地方調(diào)用時,該方法僅在來自 dunder 方法時執(zhí)行,該方法很好地包含在輸出中。
我試過這段代碼來驗證:
import sys
import traceback
from enum import Enum
class TestEnum(Enum):
"""Test enum."""
A = "A"
class MyIter:
def __init__(self):
self.i = 0
def __next__(self):
self.i += 1
if self.i <= 1:
traceback.print_stack(file=sys.stdout)
return TestEnum.A
raise StopIteration
def __iter__(self):
return self
def main():
for enum_member in MyIter():
print(f"enum member = {enum_member}.")
if __name__ == "__main__":
main()
堆棧跟蹤的最后一行打印為
File "/home/lydia/playground/demo.py", line 21, in __next__
traceback.print_stack(file=sys.stdout)
在您的原始代碼中,您在所有 dunder 方法都已返回時獲取堆棧跟蹤。因此,它們已從堆棧中刪除。
所以我認為,你想看看調(diào)用圖。我知道 IntelliJ / PyCharm 至少在付費版本中可以很好地做到這一點。
您可能還想嘗試其他工具。你覺得 pycallgraph怎么樣?
更新:
Python 使得轉儲所有函數(shù)調(diào)用的簡單列表實際上非常容易。
基本上你需要做的就是
import sys
sys.setprofile(tracefunc)
tracefunc
根據(jù)您的需要編寫。在這個 SO 問題上找到一個工作示例:How do I print functions as they are called
警告:我需要從外部 shell 啟動腳本。通過在我的 IDE 中使用播放按鈕啟動它意味著腳本永遠不會終止,而是編寫越來越多的行。我認為它與我的 IDE 完成的內(nèi)部分析相沖突。
官方文檔sys.setprofile
:https ://docs.python.org/3/library/sys.html#sys.setprofile
還有一個關于 Python 跟蹤的隨機教程:https ://pymotw.com/2/sys/tracing.html
但是請注意,根據(jù)我的經(jīng)驗,您可以對“誰在給誰打電話?”這個問題獲得最好的見解。或者“這個價值是從哪里來的?” 通過使用普通的調(diào)試器。

TA貢獻1801條經(jīng)驗 獲得超8個贊
我還對該主題進行了一些研究,因為@LydiaVanDyke 的答案中的信息促進了更好的搜索。
打印整個調(diào)用堆棧
正如@LydiaVanDyke 指出的那樣,IDE 調(diào)試器是一個非常好的方法。我使用 PyCharm,發(fā)現(xiàn)這是我最喜歡的解決方案,因為可以:
遵循函數(shù)調(diào)用 + 代碼中的確切行號
閱讀調(diào)用周圍的代碼,更好地理解打字
跳過不想調(diào)查的電話
另一種方法是 Python 的標準庫的trace
. 它提供了命令行和可嵌入的方法來打印整個調(diào)用堆棧。
還有一個是 Python 的內(nèi)置調(diào)試器模塊,pdb
. 這(通過調(diào)用pdb.set_trace()
)真的改變了我的游戲。
Profiler 輸出的可視化
gprof2dot
是另一個有用的分析器可視化工具。
查找源代碼
由于我的 IDE 的存根文件 (PyCharm),我的其他問題之一實際上并沒有看到真正的源代碼。
如何檢索Python函數(shù)的源代碼詳述了實際打印源代碼的兩種方法
使用所有這些工具,您會感到非常有能力!
添加回答
舉報