callmonitor - Alat sederhana untuk memantau dan mencatat panggilan fungsi pip install callmonitoratau klon repo ini dan:
python setup.py install Ini mudah digunakan, cukup hiasi fungsi apa pun dengan dekorator @intercept . Misalnya:
from callmonitor import intercept
@ intercept
def test_fn_2 ( x , y = 2 , z = 3 ):
pass Ini akan menyimpan input ( args , kwargs , dan argspec ) bersama dengan database panggilan ( callmonitor.DB ) ke: call-monitor/test_fn_2/<invocation count> .
callmonitor tidak menimpa output Jika folder call-monitor sudah ada (mis. Lari sebelumnya), maka folder baru call-monitor-1 , atau call-monitor-2 , dan sebagainya, dibuat. Lihat bagian pada Data Structure untuk detail lebih lanjut tentang bagaimana data ini disimpan.
Untuk menghindari proses yang berbeda dari menulis ke lokasi yang sama, callmonitor menambahkan -tid=<N> ke folder root ( call-monitor ). Saat ini callmonitor mendukung mpi4py di luar kotak: jika mpi4py.MPI.COMM_WORLD.Get_rank() > 1 , callmonitor secara otomatis mengasumsikan bahwa ia menjalankan mode multi -utmur dan menambahkan -tid=<Get_rank()> ke output. Jika program Anda multi-threaded dengan framwork lain (mis. concurrent.Futures ) maka Anda perlu memberi tahu callmonitor ID utas Anda menggunakan callmonitor.Settings :
from callmonitor import Settings
settings = Settings ()
settings . enable_multi_threading ( THREAD_ID ) Sebelum permohonan pertama intercept (database dibuat pada disk saat pertama kali diperlukan, pada saat itulah callmonitor.Settings dibaca. Setiap perubahan yang dilakukan untuk callmonitor.Settings setelah itu hanya akan berlaku jika database dibuat ulang - menggunakan callmonitor.CONTEXT.new ).
Handler Argumen Anda Sendiri Terkadang pickle tidak akan memotongnya dalam hal menghemat input fungsi - misalnya. Ketika kita perlu menyimpan tipe data mewah kita sendiri. callmonitor menyediakan cara untuk membangun penangan argumen Anda dan mendaftar ke callmonitor.REGISTRY global. Registri ditanya setiap input fungsi waktu diproses, jadi jika Anda membangun ArgHandler Anda sendiri dan menambahkannya menggunakan callmonitor.REGISTRY.add , itu akan memproses argumen data tipe yang terkait dari titik ke depan. Misalnya, numpy menyediakan fungsi save / load sendiri. Kami telah membangun (dan mendaftarkan) penangan arggumen yang tidak seperti itu seperti:
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 ) (Ingatlah bahwa callmonitor.REGISTRY.add perlu dipanggil sebelum doa pertama @intercept yang membutuhkan Handler khusus ini). Handler khusus perlu mewarisi kelas callmonitor.Handler dan mendefinisikan save , load , dan accumulator_done (yang terakhir adalah @classmethod ).
callmonitor.load(<path>) akan memuat database di <path> (lihat bagian pada Data Structure ). Misalnya:
from callmonitor import load
db = load ( "call-monitor" ) Kami sekarang bisa mendapatkan data panggilan fungsi individual dari database menggunakan DB.get :
args , kwargs = db . get ( "function_name" , invocation_count ) (yang juga akan secara otomatis memuat file .npy dan penangan khusus - ingat untuk mendaftarkannya di callmonitor.REGISTRY sebelum menjalankan db.get )
Ingat: invocation_count dimulai pada 1. Oleh karena itu untuk mengakses panggilan pertama ke test_np_1 , jalankan:
In [ 4 ]: db . get ( "test_np_1" , 1 )
Out [ 4 ]: ([ 10 , array ([ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ])], {})callmonitorKami mencoba mengaktifkan ringkasan tingkat atas dari kelas yang menghadap pengguna berikut:
REGISTRYDBDB.get_args , dan Args melalui fungsi __str__ dan __repr__ . Misalnya, callmonitor.REGISTRY menunjukkan pasangan data/pawang yang dikonfigurasi: In [ 2 ]: callmonitor . REGISTRY
Out [ 2 ]:
{
< class 'numpy.ndarray' > : < class 'callmonitor.handler.NPHandler' >
} Demikian pula objek DB menampilkan ringkasan fungsi yang disebut dan seberapa sering.
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 Memilih args , kwargs , dan argspec.defaults bisa sangat membosankan - terutama jika Anda mencoba mencari tahu nilai argumen tertentu. Oleh karena itu callmonitor.DB memberikan penambahan yang baik - get_args yang mengembalikan objek Args . callmonitor.Args adalah kelas kontainer yang menyimpan setiap argumen input berdasarkan nama sebagai yang dikaitkan. Misalnya:
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 Catatan: Konstruktor callmonitor.Args akan mengisi argumen apa pun yang tidak ada di args dan kwargs dari FullArgSpec default. Jika Anda hanya ingin menciptakan kembali fungsi asli, panggilan args dan kwargs yang dikembalikan oleh callmonitor.DB.get seharusnya cukup.
Meskipun secara teknis bukan database , mari kita panggil direktori yang dihasilkan oleh callmonitor database karena kurangnya istilah yang lebih baik. Setiap database terdiri dari file db.pkl (berisi metadata), serta folder untuk setiap fungsi (setiap panggilan fungsi disebutkan). Misalnya:
call-monitor
├── db.pkl
├── test_fn_1
│ ├── 1
│ │ └── input_descriptor.pkl
│ └── 2
│ └── input_descriptor.pkl
└── test_fn_2
└── 1
└── input_descriptor.pkl
Perhatian khusus diberikan pada input numpy - ini disebut arg_<label>.npy , di mana <label> adalah indeks argumen input, atau kw untuk kwargs. Misalnya:
call-monitor
├── db.pkl
└── test_np_1
├── 1
│ ├── arg_1.npy
│ └── input_descriptor.pkl
└── 2
├── arg_n.npy
└── input_descriptor.pkl
Pertimbangan penuh diberikan untuk menyimpan semua data panggilan dalam struktur data tunggal - bahkan mungkin database nyata ;) - tetapi untuk melakukan ini secara efisien pada skala tidak mudah, dan mungkin membuat paket ini rumit. Versi mendatang akan mencakup kemampuan untuk menggabungkan beberapa panggilan fungsi kecil ke dalam objek akumulator tunggal untuk menghindari sejumlah besar file kecil.
Versi 0.3.0 Brigns Banyak perangkat tambahan untuk callmonitor . Karena itu kami tidak dapat lagi mengaktifkan kompatibilitas mundur asli. Alat yang dapat mengonversi database versi 0.2.0 ke versi 0.3.0 (atau lebih baru) sedang dikembangkan. Versi pra-penanggalan 0.2.0 tidak lagi didukung.