小编典典

我如何打印被调用的函数

python

在调试Python脚本时,我真的很想知道整个程序的整个调用堆栈。理想的情况是,如果有一个用于python的命令行标志,它将导致Python在调用它们时打印所有函数名(我检查了man Python2.7,但是没有找到这种类型的东西)。

由于此脚本中函数的数量众多,因此,我尽量不要在每个函数和/或类的开头添加打印语句。

一个中间的解决方案是使用PyDev的调试器,放置几个断点并检查程序中给定点的调用堆栈,因此我暂时将使用这种方法。

如果存在这样的方法,我仍然希望查看程序整个生命周期内调用的所有函数的完整列表。


阅读 273

收藏
2020-12-20

共1个答案

小编典典

您可以使用跟踪函数来执行此操作(Spacedman的道具可以改进此函数的原始版本以跟踪返回并使用一些不错的缩进):

def tracefunc(frame, event, arg, indent=[0]):
      if event == "call":
          indent[0] += 2
          print("-" * indent[0] + "> call function", frame.f_code.co_name)
      elif event == "return":
          print("<" + "-" * indent[0], "exit function", frame.f_code.co_name)
          indent[0] -= 2
      return tracefunc

import sys
sys.setprofile(tracefunc)

main()   # or whatever kicks off your script

请注意,函数的代码对象通常与关联的函数具有相同的名称,但并非总是如此,因为可以动态创建函数。不幸的是,Python没有跟踪堆栈上的函数对象(我有时幻想着为此提交一个补丁)。不过,在大多数情况下,这当然“足够好”。

如果这成为问题,则可以从源代码中提取“真实的”函数名称(Python会跟踪文件名和行号),或者让垃圾回收器找出哪个函数对象引用了代码对象。可能有一个以上的函数共享代码对象,但是它们的任何名称可能都足够好。

回到四年之后,我应该提到在Python
2.6及更高版本中,使用sys.setprofile()而不是可以获得更好的性能sys.settrace()。可以使用相同的跟踪功能。只是仅当函数进入或退出时才调用profile函数,因此函数内部的内容将全速执行。

2020-12-20