[英]Line profiling class instantiation in python
我正在嘗試分析一些現有代碼。 我可以通過使用kernprof添加@profile
裝飾器來成功配置文件類方法。
有一種通用的方法來分析類實例化嗎? 我有一些類具有相當復雜的繼承結構。 當我嘗試剖析其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
這有點用處,因為我不知道正在調用實際的父__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
跟蹤器將顯示通過運行程序公開的調用關系。
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__
其中選項-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 )
它將打印出來
--- 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__()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.