Canlı Python Nesnelerini İnceleyin - inspect

Gbmdpof

Kıdemli Üye
23 Eyl 2016
2,001
11
Bu gün Interaktif Mod ile bir şey üzerinde çalışırken, burada yazdıklarımı artık dosyaya geçirebileceğimi düşündüm fakat ardından fark ettim ki yazdığım fonksiyonların çoğu oldukça geride kalmıştı. Ardından ise bu güzel inspect modülünü keşfettim.

inspect modülü, modüller, sınıflar, metodlar, fonksiyonlar, tracebakler, frame nesneleri ve kod nesneleri gibi canlı nesneler hakkında bir çok bilgiyi almaya yarayan işe yarar fonksiyonlar sunan bir modüldür. Örnek olarak bir sınıfın metodlarına erişebilir, benim yaptığım gibi o metodların kaynak koduna ulaşabilir, bir fonksiyon için argüman listesi çıkarabilir veya detaylı bir traceback göstermek için gereken tüm verileri alabilirsiniz.

Bu modül tarafından sunular dört temel hizmet vardır: tür kontrolü, kaynak kodunu alma, sınıf ve fonksiyon inceleme ve interpreter stack'i inceleme.

Ben, bu yazıda sadece karşınıza daha çok çıkabilecek örnekler üzerinden gideceğim fakat inspect modülünün tam kullanımı için orijinal dökümantasyona bakabilirsiniz: https://docs.python.org/3/library/inspect.html

Bu modülü incelemeye başlamak için örneklerde kullanmak için bir modül yazalım:

Kod:
[font=monospace][color=#66d9ef]class[/color] [color=#a6e22e]class1[/color][color=#f8f8f2]:[/color][color=#f8f8f2]
    [/color][color=#66d9ef]def[/color] [color=#a6e22e]__init__[/color][color=#f8f8f2]([/color][color=#f8f8f2]self[/color][color=#f8f8f2],[/color] [color=#f8f8f2]arg1[/color][color=#f8f8f2]):[/color][color=#f8f8f2]
        [/color][color=#f8f8f2]self[/color][color=#f92672].[/color][color=#f8f8f2]arg1[/color] [color=#f92672]=[/color] [color=#f8f8f2]arg1[/color][color=#f8f8f2]

    [/color][color=#66d9ef]def[/color] [color=#a6e22e]sum[/color][color=#f8f8f2]([/color][color=#f8f8f2]self[/color][color=#f8f8f2],[/color] [color=#f8f8f2]arg2[/color][color=#f8f8f2]):[/color][color=#f8f8f2]
        [/color][color=#66d9ef]return[/color] [color=#f8f8f2]self[/color][color=#f92672].[/color][color=#f8f8f2]arg1[/color] [color=#f92672]+[/color] [color=#f8f8f2]arg2[/color][color=#f8f8f2]

[/color][color=#66d9ef]class[/color] [color=#a6e22e]class2[/color][color=#f8f8f2]([/color][color=#f8f8f2]class1[/color][color=#f8f8f2]):[/color][color=#f8f8f2]
    [/color][color=#66d9ef]def[/color] [color=#a6e22e]multiply[/color][color=#f8f8f2]([/color][color=#f8f8f2]self[/color][color=#f8f8f2],[/color] [color=#f8f8f2]arg2[/color][color=#f8f8f2]):[/color][color=#f8f8f2]
        [/color][color=#66d9ef]return[/color] [color=#f8f8f2]self[/color][color=#f92672].[/color][color=#f8f8f2]arg1[/color] [color=#f92672]*[/color] [color=#f8f8f2]arg2[/color][color=#f8f8f2]

[/color][color=#66d9ef]def[/color] [color=#a6e22e]func1[/color][color=#f8f8f2]([/color][color=#f8f8f2]arg1[/color][color=#f8f8f2]):[/color][color=#f8f8f2]
    [/color][color=#66d9ef]return[/color] [color=#f8f8f2]arg1[/color] [color=#f92672]**[/color] [color=#f8f8f2]arg1[/color][color=#f8f8f2]

[/color][color=#f8f8f2]obj[/color] [color=#f92672]=[/color] [color=#f8f8f2]class2[/color][color=#f8f8f2]()[/color][color=#f8f8f2]
[/color][/font]

Şimdi ise bu modülü importlayalım ve ardından bütün inspect.getmembers ile incelemeye başlayalım:

Kod:
[font=monospace][color=#f92672]import[/color] [color=#f8f8f2]sample[/color][color=#f8f8f2]
[/color][color=#f92672]import[/color] [color=#f8f8f2]inspect[/color][color=#f8f8f2]

[/color][color=#66d9ef]for[/color] [color=#f8f8f2]name[/color][color=#f8f8f2],[/color] [color=#f8f8f2]value[/color] [color=#f92672]in[/color][color=#f8f8f2]  [/color][color=#f8f8f2]inspect[/color][color=#f92672].[/color][color=#f8f8f2]getmembers[/color][color=#f8f8f2]([/color][color=#f8f8f2]sample[/color][color=#f8f8f2]):[/color][color=#f8f8f2]
    [/color][color=#66d9ef]if[/color] [color=#f92672]not[/color] [color=#f8f8f2]name[/color][color=#f92672].[/color][color=#f8f8f2]startswith[/color][color=#f8f8f2]([/color][color=#e6db74]'__'[/color][color=#f8f8f2]):[/color][color=#f8f8f2]
        [/color][color=#66d9ef]print[/color][color=#f8f8f2]([/color][color=#f8f8f2]name[/color][color=#f8f8f2],[/color] [color=#f8f8f2]value[/color][color=#f8f8f2])[/color][color=#f8f8f2]
[/color][/font]

Bu kodu çalıştırınca ise __ ile başlayanlar dışında (built-in olarak gelen ve şu an ihtiyacımız olmayan şeyler) modülün bütün üyelerini bize gösteriyor.

Kod:
λ python3 inspector.py
class1 <class 'sample.class1'>
class2 <class 'sample.class2'>
func1 <function func1 at 0x7fd2a84d16a8>
obj <sample.class2 object at 0x7fd2a84b20f0>

inspect.getmembers fonksiyonu, aynı zamanda isteğe bağlı bir argüman daha alıyor. Bu argüman ile de sadece verdiğimiz türe uyan üyeler dönüyor. Örneğin sadece sınıfları almak istersek, kodumuzu aşağıdaki şekilde değiştirebiliriz.

Kod:
[font=monospace][color=#f92672]import[/color] [color=#f8f8f2]sample[/color][color=#f8f8f2]
[/color][color=#f92672]import[/color] [color=#f8f8f2]inspect[/color][color=#f8f8f2]

[/color][color=#66d9ef]for[/color] [color=#f8f8f2]name[/color][color=#f8f8f2],[/color] [color=#f8f8f2]value[/color] [color=#f92672]in[/color][color=#f8f8f2]  [/color][color=#f8f8f2]inspect[/color][color=#f92672].[/color][color=#f8f8f2]getmembers[/color][color=#f8f8f2]([/color][color=#f8f8f2]sample[/color][color=#f8f8f2],[/color] [color=#f8f8f2]inspect[/color][color=#f92672].[/color][color=#f8f8f2]isclass[/color][color=#f8f8f2]):[/color][color=#f8f8f2]
    [/color][color=#66d9ef]print[/color][color=#f8f8f2]([/color][color=#f8f8f2]name[/color][color=#f8f8f2],[/color] [color=#f8f8f2]value[/color][color=#f8f8f2])[/color][color=#f8f8f2]
[/color][/font]

Bunda ise çıktı, sadece sınıfları aldığımız için yukarıdakinin ilk 2 satırı olacak.

Kod:
λ python3 inspector.py
class1 <class 'sample.class1'>
class2 <class 'sample.class2'>

Aynı zamanda sadece modülleri değil, modüllerin içindekiler hakkında da bilgi alabiliriz. Örneğin class1'in içindeki fonksiyonları bulan bir script yazalım.

Kod:
[font=monospace][color=#f92672]import[/color] [color=#f8f8f2]sample[/color][color=#f8f8f2]
[/color][color=#f92672]import[/color] [color=#f8f8f2]inspect[/color][color=#f8f8f2]

[/color][color=#66d9ef]print[/color][color=#f8f8f2]([/color][color=#f8f8f2]inspect[/color][color=#f92672].[/color][color=#f8f8f2]getmembers[/color][color=#f8f8f2]([/color][color=#f8f8f2]sample[/color][color=#f92672].[/color][color=#f8f8f2]class1[/color][color=#f8f8f2],[/color] [color=#f8f8f2]inspect[/color][color=#f92672].[/color][color=#f8f8f2]isfunction[/color][color=#f8f8f2]))[/color][color=#f8f8f2]
[/color][/font]

Bu da sınıfımızda sadece __init__ ve sum fonksiyonları olduğu için onları printleyecektir. Çıktımız da şu şekilde olacaktır.

Kod:
λ python3 inspector.py 
[('__init__', <function class1.__init__ at 0x7f1a0dc1dc80>), ('sum', <function class1.sum at 0x7f1a0dc1dd08>)]

Aynı şekilde sınıfları inceleyebildiğimiz gibi nesneleri de inceleyebiliriz. Ki bu bazen nesne hakkında fazla bilgiye sahip olmadığımızda oldukça işimize yarayabilir. Ayrıca bir sınıfın kullanımı hakkında bilgiye sahip olmadığımızda da docstringleri okumamız gerekebiliyor. Bunu normalde __doc__ ile elde edebilsek de inspect modülü ile temizlenmiş bir şekilde docstring'i ekle edebiliyoruz.

mMJvZZ.png


Bu temizleme hakkında daha fazla bilgi için CPython kaynak kodundan inspect.py dosyasında işaretlediğim satırları inceleyebilirsiniz: https://github.com/python/cpython/blob/master/Lib/inspect.py#L616-L643

Şimdi ise beni dakikalarca yukarı ok tuşuna basmaktan kurtaran kaynak kodu okuma özelliğine bakalım. Örneğin, class1'in kaynak kodunu okuyalım bunun için:

Kod:
[font=monospace][color=#f92672]import[/color] [color=#f8f8f2]sample[/color][color=#f8f8f2]
[/color][color=#f92672]import[/color] [color=#f8f8f2]inspect[/color][color=#f8f8f2]

[/color][color=#66d9ef]print[/color][color=#f8f8f2]([/color][color=#f8f8f2]inspect[/color][color=#f92672].[/color][color=#f8f8f2]getsource[/color][color=#f8f8f2]([/color][color=#f8f8f2]sample[/color][color=#f92672].[/color][color=#f8f8f2]class1[/color][color=#f8f8f2]))[/color][color=#f8f8f2]
[/color][/font]

Çıktı olarak, kaynak kodumuzu verdi:
Kod:
λ python3 inspector.py 
class class1:
    def __init__(self, arg1):
        self.arg1 = arg1

    def sum(self, arg2):
        return self.arg1 + arg2

Bu getsource'un bir diğer güzel yanı ise yorum satırları ve docstringleri de bize vermesidir:
Kod:
class class1:
    def __init__(self, arg1):
        self.arg1 = arg1 # set self.arg1

    def sum(self, arg2):
        """sum function"""
        return self.arg1 + arg2

Ayrıca kaynak kodunu almadan bir metodun argüman olarak neler aldığını öğrenmek istersek de bu metodun imzasını inspect.signature ile alabiliriz:

Kod:
[font=monospace][color=#f92672]import[/color] [color=#f8f8f2]sample[/color][color=#f8f8f2]
[/color][color=#f92672]import[/color] [color=#f8f8f2]inspect[/color][color=#f8f8f2]

[/color][color=#66d9ef]print[/color][color=#f8f8f2]([/color][color=#f8f8f2]inspect[/color][color=#f92672].[/color][color=#f8f8f2]signature[/color][color=#f8f8f2]([/color][color=#f8f8f2]sample[/color][color=#f92672].[/color][color=#f8f8f2]func1[/color][color=#f8f8f2]))[/color][color=#f8f8f2]
[/color][/font]

Kod:
λ python3 inspector.py
(arg1)

Ben burada örnek bir fonksiyon yazdığım için argüman adını açıklayıcı olmayan arg1 yapmıştım fakat normalde açıklayıcı argümanlar bulmanız daha olası. Sizin de kod yazarken argüman adlarınızı dikkatli seçmenizde fayda var bu sebepten.

Evet, bunlar ile artık Python nesneleri hakkında detaylı bilgiye sahip olabiliyoruz. Eğer bu modülü kullanarak bir şeyler yazmak isterseniz, kendi dökümantasyon oluşturucunuzu yazabilirsiniz.
 
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.