簡體   English   中英

python中的行分析類實例化

[英]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應該包含最少的代碼來初始化您的類。

將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__()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM