nau*_*101 2 python inheritance instantiation line-profiler
我有一些我正在尝试分析的现有代码。我可以通过@profile使用kernprof添加装饰器来成功地排列配置文件类方法。
有没有一种通用的方法来分析类实例化?我有几个类具有非常复杂的继承结构。当我尝试分析它们的 init 函数时,我得到如下信息:
Line # Hits Time Per Hit % Time Line Contents
==============================================================
179 def __init__(self, data):
180 1 8910739.0 8910739.0 100.0 super().__init__(data)
181 1 10.0 10.0 0.0 self.mortgage_rate = 5.2 # rate in percentage
Run Code Online (Sandbox Code Playgroud)
这有点没用,因为我不知道__init__正在调用什么实际的父函数(这个类有 2 个父级,每个父级都有一个或多个父级)。
有什么办法可以做得更好吗?例如,有没有办法自动潜入每条线,并分析它调用的线(深度有限)?
有很多方法:
trace模块标准 python 库中的trace模块提供了一个方便的函数来逐行跟踪程序的执行。因此,很容易确定您的__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
Run Code Online (Sandbox Code Playgroud)
跟踪器将显示通过运行程序暴露的调用关系。
MyDependency.Fourth.__init__ -> MyDependency.Second.__init__
MyDependency.Second.__init__ -> MyDependency.Third.__init__
MyDependency.Third.__init__ -> MyDependency.First.__init__
MyClass.Child.__init__ -> MyDependency.Fourth.__init__
Run Code Online (Sandbox Code Playgroud)
该trace模块还有一个 CLI。上面的python代码相当于这个shell命令:
python -m trace -T test.py | grep __init__
Run Code Online (Sandbox Code Playgroud)
其中 option-T相当于countcallers=True. 目标脚本test.py应该包含最少的代码来初始化您的类。
现在您知道在类初始化中调用的模块、类和方法的名称。然后你可以@profile为这些函数添加装饰器。附带说明:不需要修改每个模块的源代码来添加装饰器。只需将它们导入您的主模块并运行即可
profile.add_function(MyDependency.Third.__init__)
获得相同的效果。
如果要获得所有调用的 Python 代码行的时间顺序跟踪,请使用以下选项
tracer = trace.Trace( ignoredirs=[sys.prefix, sys.exec_prefix ], trace=1, count=0, timing=True )
Run Code Online (Sandbox Code Playgroud)
它会打印出来
--- modulename: MyMod, funcname: __init__
0.00 MyMod.py(6): super().__init__()
--- modulename: MyDependency, funcname: __init__
0.00 MyDependency.py(17): super().__init__()
...
Run Code Online (Sandbox Code Playgroud)
其中第一列是步行时钟时间。
sys.setprofile方法您可以通过该sys.setprofile方法注册回调函数。它将接收堆栈转换事件(当函数被调用或返回时)。每个事件都带有一个堆栈帧对象,您可以从中记录模块、类和调用的函数。
这种方法会给你最大的灵活性。例如,您可以使用堆栈深度或执行时间长度过滤掉函数调用。有关用法示例,请参阅我的旧帖子以了解类似问题。
以上结果基于以下取自另一篇文章的模块/类结构。
文件“MyDependency.py”
class First:
...
class Second(First):
...
class Third(First):
...
class Fourth(Second, Third):
...
Run Code Online (Sandbox Code Playgroud)
文件“MyModel.py”
from MyDependency import Fourth
class MyClass(Fourth):
def __init__(self):
super().__init__()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1130 次 |
| 最近记录: |