2 回答
TA贡献1811条经验 获得超6个赞
我认为,使用堆栈跟踪,您正在寻找错误的地方。当您print_stack从一个地方调用时,该方法仅在来自 dunder 方法时执行,该方法很好地包含在输出中。
我试过这段代码来验证:
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 方法都已返回时获取堆栈跟踪。因此,它们已从堆栈中删除。
所以我认为,你想看看调用图。我知道 IntelliJ / PyCharm 至少在付费版本中可以很好地做到这一点。
您可能还想尝试其他工具。你觉得 pycallgraph怎么样?
更新:
Python 使得转储所有函数调用的简单列表实际上非常容易。
基本上你需要做的就是
import sys
sys.setprofile(tracefunc)
tracefunc
根据您的需要编写。在这个 SO 问题上找到一个工作示例:How do I print functions as they are called
警告:我需要从外部 shell 启动脚本。通过在我的 IDE 中使用播放按钮启动它意味着脚本永远不会终止,而是编写越来越多的行。我认为它与我的 IDE 完成的内部分析相冲突。
官方文档sys.setprofile
:https ://docs.python.org/3/library/sys.html#sys.setprofile
还有一个关于 Python 跟踪的随机教程:https ://pymotw.com/2/sys/tracing.html
但是请注意,根据我的经验,您可以对“谁在给谁打电话?”这个问题获得最好的见解。或者“这个价值是从哪里来的?” 通过使用普通的调试器。
TA贡献1801条经验 获得超8个赞
我还对该主题进行了一些研究,因为@LydiaVanDyke 的答案中的信息促进了更好的搜索。
打印整个调用堆栈
正如@LydiaVanDyke 指出的那样,IDE 调试器是一个非常好的方法。我使用 PyCharm,发现这是我最喜欢的解决方案,因为可以:
遵循函数调用 + 代码中的确切行号
阅读调用周围的代码,更好地理解打字
跳过不想调查的电话
另一种方法是 Python 的标准库的trace
. 它提供了命令行和可嵌入的方法来打印整个调用堆栈。
还有一个是 Python 的内置调试器模块,pdb
. 这(通过调用pdb.set_trace()
)真的改变了我的游戏。
Profiler 输出的可视化
gprof2dot
是另一个有用的分析器可视化工具。
查找源代码
由于我的 IDE 的存根文件 (PyCharm),我的其他问题之一实际上并没有看到真正的源代码。
如何检索Python函数的源代码详述了实际打印源代码的两种方法
使用所有这些工具,您会感到非常有能力!
添加回答
举报