callmonitor一個簡單的監視和日誌功能調用的工具pip install callmonitor或克隆此回購和:
python setup.py install它易於使用,只需用@intercept Decorator裝飾任何功能即可。例如:
from callmonitor import intercept
@ intercept
def test_fn_2 ( x , y = 2 , z = 3 ):
pass這將將輸入( args , kwargs和argspec )以及CALL數據庫( callmonitor.DB )保存為: call-monitor/test_fn_2/<invocation count> 。
callmonitor不會覆蓋輸出如果call-monitor文件夾已經存在(例如,以前的運行),則創建了新文件夾call-monitor-1或call-monitor-2 ,依此類推。有關如何保存此數據的更多詳細信息,請參見Data Structure的部分。
為了避免從編寫到同一位置的不同過程, callmonitor將-tid=<N>附加到root( call-monitor )文件夾。當前callmonitor框外支持mpi4py :如果mpi4py.MPI.COMM_WORLD.Get_rank() > 1 , callmonitor自動假設其正在運行IM多線程模式,並附加-tid=<Get_rank()>向輸出。如果您的程序為多線程(例如concurrent.Futures )多線程,則您需要使用callmonitor.Settings告訴callmonitor您的線程ID:
from callmonitor import Settings
settings = Settings ()
settings . enable_multi_threading ( THREAD_ID )在第一次intercept攔截之前(第一次需要在磁盤上創建數據庫,是在callmonitor.CONTEXT.new callmonitor.Settings讀取callmonitor.Settings時候。
Handler程序有時, pickle不會用保存功能輸入來削減它 - 例如。當我們需要保存自己的精美數據類型時。 callmonitor提供了一種構建您的向下參數處理程序並註冊到Global callmonitor.REGISTRY方法。每次處理函數輸入時都會查詢註冊表,因此,如果您構建自己的ArgHandler並使用G callmonitor.REGISTRY.add添加它們,它將從該點開始處理關聯數據類型的任何參數。例如, numpy提供了自己的save / load功能。我們已經構建(並註冊)一個Numpy Arggument處理程序這樣:
import numpy as np
from os . path import join
from callmonitor import Handler , REGISTRY
class NPHandler ( Handler ):
def load ( self , path ):
self . data = np . load ( join ( path , f"arg_ { self . target } .npy" ))
def save ( self , path ):
np . save ( join ( path , f"arg_ { self . target } .npy" ), self . data )
@ classmethod
def accumulator_done ( cls ):
pass
REGISTRY . add ( np . ndarray , NPHandler ) (請記住,在需要此特定Handler的@intercept的第一次調用之前,需要調用callmonitor.REGISTRY.add )。自定義處理程序需要繼承callmonitor.Handler類並定義save , load和accumulator_done (最後一個是@classmethod )。
callmonitor.load(<path>)將在<path>上加載數據庫(請參閱Data Structure的部分)。例如:
from callmonitor import load
db = load ( "call-monitor" )現在,我們可以使用DB.get從數據庫中獲取單個函數調用數據:
args , kwargs = db . get ( "function_name" , invocation_count ) (這也將自動加載.npy文件和任何自定義處理程序 - 請記住在執行db.get之前在callmonitor.REGISTRY中註冊這些文件)
請記住: invocation_count從1開始。因此,要訪問第一個調用test_np_1 ,請運行:
In [ 4 ]: db . get ( "test_np_1" , 1 )
Out [ 4 ]: ([ 10 , array ([ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ])], {})callmonitor互動我們嘗試啟用以下以下用戶類別的頂級摘要:
REGISTRYDBDB.get_args ,並通過__str__和__repr__函數進行Args 。例如, callmonitor.REGISTRY顯示了配置了哪些數據類型/處理程序對: In [ 2 ]: callmonitor . REGISTRY
Out [ 2 ]:
{
< class 'numpy.ndarray' > : < class 'callmonitor.handler.NPHandler' >
}同樣, DB對象顯示了調用函數摘要以及一次。
In [ 3 ]: db = callmonitor . load ( "call-monitor" )
In [ 4 ]: db
Out [ 4 ]:
{
Locked : True
test_np_1 : {
calls : 2
args : [ 'x' , 'n' ]
defaults : None
}
}Args容器挑選args , kwargs和argspec.defaults可能非常乏味 - 尤其是如果您想找出特定參數的價值。因此, callmonitor.DB提供了一個添加getter get_args返回Args對象。 callmonitor.Args是容器類,可將每個輸入參數按名稱作為屬性存儲。例如:
In [ 3 ]: args = db . get_args ( "test_fn_1" , 1 )
In [ 4 ]: args
Out [ 4 ]: dict_keys ([ 'x' , 'y' , 'z' ])
In [ 5 ]: args . x
Out [ 5 ]: 1注意: callmonitor.Args構造函數將填充FullArgSpec默認值中不在args和kwargs中的任何參數。如果您只想重新創建原始功能,請調用args和callmonitor.DB.get返回的誇kwargs 。
雖然從技術上講不是數據庫,但讓我們將callmonitor生成的目錄稱為數據庫,因為缺乏更好的術語。每個數據庫都由一個db.pkl文件(包含元數據)以及每個函數的文件夾(枚舉每個函數調用)。例如:
call-monitor
├── db.pkl
├── test_fn_1
│ ├── 1
│ │ └── input_descriptor.pkl
│ └── 2
│ └── input_descriptor.pkl
└── test_fn_2
└── 1
└── input_descriptor.pkl
特別注意numpy輸入 - 這些稱為arg_<label>.npy ,其中<label>是輸入參數的索引,或KWARGS的kw 。例如:
call-monitor
├── db.pkl
└── test_np_1
├── 1
│ ├── arg_1.npy
│ └── input_descriptor.pkl
└── 2
├── arg_n.npy
└── input_descriptor.pkl
全面考慮將所有呼叫數據保存在單個數據結構中 - 甚至可能是一個真實的數據庫;) - 但是在大規模上有效地進行此操作並不容易,並且可能會使此軟件包變得笨拙。未來版本將包括將多個小功能調用融合到單個累加器對像中以避免大量小文件的能力。
版本0.3.0 Brign為callmonitor提供了許多增強功能。因此,我們再也無法啟用本地向後兼容性。當前正在開發一個可以將0.2.0數據庫版本的數據庫轉換為0.3.0(或更高版本)的工具。預期0.2.0的版本不再支持。