有很多方法:
trace
模块_
标准 python 库中的跟踪模块提供了一个方便的函数来逐行跟踪程序的执行。因此,很容易找出您的__init__
方法调用了哪个函数。
尝试在 python shell 中运行以下代码
from MyMod import MyClass
# Do necessary preparation for your module HERE
# --- Setup and start tracing ---
import sys, trace
tracer = trace.Trace( trace=0, count=0, timing=True, countcallers=True)
tracer.run('MyClass()') # init your class and track the function calls
tracer.results().write_results(show_missing=False) # print result to the screen
跟踪器将显示通过运行程序暴露的调用关系。
MyDependency.Fourth.__init__ -> MyDependency.Second.__init__
MyDependency.Second.__init__ -> MyDependency.Third.__init__
MyDependency.Third.__init__ -> MyDependency.First.__init__
MyClass.Child.__init__ -> MyDependency.Fourth.__init__
该trace
模块还有一个 CLI。上面的 python 代码等价于这个 shell 命令:
python -m trace -T test.py | grep __init__
其中 option-T
等价于countcallers=True
. 目标脚本test.py
应该包含最少的代码来初始化你的类。
将 line-profiler 添加到调用的函数
现在您知道了在类初始化中调用的模块、类和方法的名称。然后你可以@profile
为这些函数添加装饰器。附带说明:不需要修改每个模块的源代码来添加装饰器。只需将它们导入您的主模块并运行
profile.add_function(MyDependency.Third.__init__)
将具有相同的效果。
如果您想按时间顺序跟踪调用的所有 Python 代码行,请使用以下选项
tracer = trace.Trace( ignoredirs=[sys.prefix, sys.exec_prefix ], trace=1, count=0, timing=True )
它会打印出来
--- modulename: MyMod, funcname: __init__
0.00 MyMod.py(6): super().__init__()
--- modulename: MyDependency, funcname: __init__
0.00 MyDependency.py(17): super().__init__()
...
其中第一列是步行时钟时间。
sys.setprofile
方法_
sys.setprofile
您可以通过该方法注册一个回调函数。它将接收堆栈转换事件(当函数被调用或返回时)。每个事件都带有一个堆栈框架对象,您可以从中记录模块、类和调用的函数。
这种方法会给你最大的灵活性。例如,您可以过滤掉具有堆栈深度或执行时间长度的函数调用。有关用法示例,请参阅我较早的帖子以获取类似的问题。
上述示例的文件结构
以上结果基于从另一篇文章中获取的以下模块/类结构。
文件“MyDependency.py”
class First:
...
class Second(First):
...
class Third(First):
...
class Fourth(Second, Third):
...
文件“MyModel.py”
from MyDependency import Fourth
class MyClass(Fourth):
def __init__(self):
super().__init__()