Python Hata Ayıklayıcıyı Kullanma
Giriş
Yazılım geliştirme sürecinde hata ayıklama, yazılımın doğru çalışmasını engelleyen sorunları bulma ve çözme işlemidir.
Python hata ayıklayıcısı
, Python programları için bir hata ayıklama ortamı sağlar. Şartlı durma noktaları belirlemeyi, kaynak kodu birer satır olarak takip etmeyi, yığın incelemeyi ve daha fazlasını destekler.
Python Hata Ayıklayıcı ile Etkileşimli Çalışma
Python hata ayıklayıcı, pdb
adlı bir modül olarak standart Python dağıtımının bir parçası olarak gelir. Hata ayıklayıcı ayrıca genişletilebilir ve Pdb
sınıfı olarak tanımlanmıştır.
Bilgi: Bu eğitici yazıdaki örnek kodları takip etmek için, yerel sisteminizde bir Python etkileşimli kabuğu açmak amacıyla python3
komutunu çalıştırın. Daha sonra, >>>
isteminden sonra örnekleri kopyalayabilir, yapıştırabilir veya düzenleyebilirsiniz.
Kısa bir programla başlayacağız. Bu programda iki genel değişken, iç içe bir döngü oluşturan bir fonksiyon ve if __name__ == '__main__':
yapısı kullanılarak nested_loop()
fonksiyonu çağrılacaktır.
looping.py
sayi_listesi = [500, 600, 700]
harf_listesi = ['x', 'y', 'z']
def ic_ice_dongu():
for sayi in sayi_listesi:
print(sayi)
for harf in harf_listesi:
print(harf)
if __name__ == '__main__':
ic_ice_dongu()
Bu programı Python hata ayıklayıcı ile aşağıdaki komut kullanılarak çalıştırabiliriz:
$ python -m pdb looping.py
-m
komut satırı bayrağı, herhangi bir Python modülünü sizin için içe aktarır ve bir betik olarak çalıştırır. Bu durumda, yukarıda gösterildiği gibi komuta geçirdiğimiz pdb
modülünü içe aktarıyor ve çalıştırıyoruz.
Bu komutu çalıştırdığınızda aşağıdaki çıktıyı alırsınız:
Çıktı:
> /Users/sammy/looping.py(1)<module>()
-> sayi_listesi = [500, 600, 700]
(Pdb)
Çıktıda, ilk satır mevcut modül adını (<module>
ile belirtilmiş) bir dizin yolu ile birlikte içerir ve ardından gelen yazdırılmış satır numarasını gösterir (bu durumda 1, ancak bir yorum satırı veya başka çalıştırılabilir olmayan bir satır varsa daha yüksek bir numara olabilir). İkinci satır, burada yürütülen kaynak kodun mevcut satırını gösterir ve pdb
, hata ayıklama için etkileşimli bir konsol sağlar. Komutlarını öğrenmek için help
komutunu, belirli bir komut hakkında daha fazla bilgi almak için help komut_adı
komutunu kullanabilirsiniz. pdb
konsolunun, Python etkileşimli kabuğundan farklı olduğunu unutmayın.
Python hata ayıklayıcısı, programınızın sonuna ulaştığında otomatik olarak yeniden başlar. pdb
konsolundan çıkmak istediğinizde, quit
veya exit
komutunu yazabilirsiniz. Programın herhangi bir yerinde açıkça yeniden başlatmak isterseniz, bunu run
komutuyla yapabilirsiniz.
Bir Programda İlerlemek için Hata Ayıklayıcı Kullanma
Python hata ayıklayıcı
ile program üzerinde çalışırken list
, step
ve next
komutlarını kodunuzda ilerlemek için muhtemelen kullanacaksınız. Bu bölümde bu komutları ele alacağız.
Kabuk içinde, mevcut satırın etrafındaki bağlamı almak için list
komutunu yazabiliriz. Yukarıda gösterilen programın ilk satırındaki (sayi_listesi = [500, 600, 700]
) durumu şu şekilde görünür:
(Pdb) list
1 -> sayi_listesi = [500, 600, 700]
2 harf_listesi = ['x', 'y', 'z']
3
4
5 def ic_ice_dongu():
6 for sayi in sayi_listesi:
7 print(sayi)
8 for harf in harf_listesi:
9 print(harf)
10
11 if __name__ == '__main__':
(Pdb)
Mevcut satır ->
karakterleri ile belirtilmiştir, ki bu durumda program dosyasının ilk satırıdır.
Bu nispeten kısa bir program olduğu için, list
komutuyla neredeyse tüm programı geri alıyoruz. Argüman sağlamadan kullanıldığında, list
komutu mevcut satırın etrafındaki 11 satırı döndürür, ancak hangi satırların dahil edileceğini de belirtebilirsiniz:
(Pdb) list 3, 7
3
4
5 def ic_ice_dongu():
6 for sayi in sayi_listesi:
7 print(sayi)
(Pdb)
Burada list 3, 7
komutunu kullanarak 3-7 satırların görüntülenmesini istedik.
Programda satır satır ilerlemek için step veya next komutlarını kullanabiliriz:
(Pdb) step
> /Users/sammy/looping.py(2)<module>()
-> harf_listesi = ['x', 'y', 'z']
(Pdb)
(Pdb) next
> /Users/sammy/looping.py(2)<module>()
-> harf_listesi = ['x', 'y', 'z']
(Pdb)
step
ve next
arasındaki fark, step
bir çağrılan fonksiyonun içine dururken, next
çağrılan fonksiyonları çalıştırır ve yalnızca mevcut fonksiyonun bir sonraki satırında durur. Bu farkı, fonksiyonlarla çalışırken daha net görebiliriz.
step
Komutu ile Döngülerde Adım Adım İlerleme
step
komutu, bir fonksiyon çalıştırıldığında döngülerde tek tek adımları gösterir. Bu komut, döngünün tam olarak ne yaptığını izlemeyi sağlar. Önce print(number)
ile bir sayıyı yazdırır, ardından harfleri yazdırmak için print(letter)
ile devam eder, sonra tekrar sayıya döner ve bu şekilde döngü ilerler:
(Pdb) step
> /Users/sammy/looping.py(5)<module>()
-> def ic_ice_dongu():
(Pdb) step
> /Users/sammy/looping.py(11)<module>()
-> if __name__ == '__main__':
(Pdb) step
> /Users/sammy/looping.py(12)<module>()
-> ic_ice_dongu()
(Pdb) step
--Call--
> /Users/sammy/looping.py(5)ic_ice_dongu()
-> def ic_ice_dongu():
(Pdb) step
> /Users/sammy/looping.py(6)ic_ice_dongu()
-> for sayi in sayi_listesi:
(Pdb) step
> /Users/sammy/looping.py(7)ic_ice_dongu()
-> print(sayi)
(Pdb) step
500
> /Users/sammy/looping.py(8)ic_ice_dongu()
-> for harf in harf_listesi:
(Pdb) step
> /Users/sammy/looping.py(9)ic_ice_dongu()
-> print(harf)
(Pdb) step
x
> /Users/sammy/looping.py(8)ic_ice_dongu()
-> for harf in harf_listesi:
(Pdb) step
> /Users/sammy/looping.py(9)ic_ice_dongu()
-> print(harf)
(Pdb) step
y
> /Users/sammy/looping.py(8)ic_ice_dongu()
-> for harf in harf_listesi:
(Pdb)
Bunun aksine, next
komutu fonksiyonu adım adım göstermeden tamamen çalıştırır. Mevcut oturumdan çıkmak için exit
komutunu kullanarak çıkabilir ve hata ayıklayıcıyı yeniden başlatabilirsiniz:
$ python -m pdb looping.py
Şimdi next
komutunu kullanarak devam edebiliriz:
(Pdb) next
> /Users/sammy/looping.py(5)<module>()
-> def ic_ice_dongu():
(Pdb) next
> /Users/sammy/looping.py(11)<module>()
-> if __name__ == '__main__':
(Pdb) next
> /Users/sammy/looping.py(12)<module>()
-> ic_ice_dongu()
(Pdb) next
500
x
y
z
600
x
y
z
700
x
y
z
--Return--
> /Users/sammy/looping.py(12)<module>()->None
-> ic_ice_dongu()
(Pdb)
Kodunuzu incelerken bir değişkene atanan değeri görmek isteyebilirsiniz. Bu, pp
komutuyla yapılabilir. Bu komut, bir ifadeyi pprint
modülünü kullanarak daha okunabilir bir biçimde yazdırır:
(Pdb) pp sayi_listesi
[500, 600, 700]
(Pdb)
Pek çok pdb
komutunun kısa yolları mevcuttur. Örneğin, step
komutunun kısaltması s
, next
komutunun kısaltması n
'dir. Son kullandığınız komutu tekrar çağırmak için istemde ENTER
tuşuna basabilirsiniz.
###Durma Noktaları (Breakpoints)
Daha büyük programlarla çalışırken, tüm programı adım adım geçmek yerine belirli fonksiyonlara veya satırlara odaklanmak isteyebilirsiniz. Bunun için break
komutuyla durma noktaları ayarlayabilirsiniz. Program, belirtilen durma noktasına kadar çalıştırılır.
Durma noktası eklendiğinde hata ayıklayıcı buna bir numara atar. Bu numaralar artan tam sayılardır ve durma noktalarıyla çalışırken bunlara başvurabilirsiniz.
Durma noktalarını belirli satır numaralarına yerleştirmek için <program_dosyası>:<satır_no>
sözdizimini kullanabilirsiniz:
(Pdb) break looping.py:5
Breakpoint 1 at /Users/sammy/looping.py:5
(Pdb)
Bir fonksiyonun tanımlandığı yere durma noktası yerleştirmek için:
(Pdb) break looping.ic_ice_dongu
Breakpoint 1 at /Users/sammy/looping.py:5
(Pdb)
Mevcut durma noktalarını kaldırmak için clear
yazabilir ve ardından y tuşuna basabilirsiniz.
Şartlı bir durma noktası ayarlayarak, belirli bir koşul sağlandığında durmasını sağlayabilirsiniz:
(Pdb) break looping.py:7, sayi > 500
Breakpoint 1 at /Users/sammy/looping.py:7
(Pdb)
Eğer continue
komutunu uygularsak, program number
değişkeni 500'den büyük bir değere sahip olduğunda (örneğin, dış döngünün ikinci iterasyonunda 600 olduğunda) durur:
(Pdb) continue
500
x
y
z
> /Users/sammy/looping.py(7)nested_loop()
-> print(number)
(Pdb)
Mevcut durma noktalarını listelemek için break komutunu argümansız çalıştırabilirsiniz. Bu komut, durma noktalarının ayrıntılarını gösterir:
(Pdb) break
Num Type Disp Enb Where
1 breakpoint keep yes at /Users/sammy/looping.py:7
stop only if number > 500
breakpoint already hit 2 times
(Pdb)
Bir durma noktasını devre dışı bırakmak için disable
komutunu ve durma noktasının numarasını kullanabilirsiniz:
(Pdb) break looping.py:11
Breakpoint 2 at /Users/sammy/looping.py:11
(Pdb) disable 1
Disabled breakpoint 1 at /Users/sammy/looping.py:7
(Pdb) break
Num Type Disp Enb Where
1 breakpoint keep no at /Users/sammy/looping.py:7
stop only if number > 500
breakpoint already hit 2 times
2 breakpoint keep yes at /Users/sammy/looping.py:11
(Pdb)
Bir durma noktasını tekrar etkinleştirmek için enable
komutunu, tamamen kaldırmak için ise clear komutunu kullanabilirsiniz:
(Pdb) enable 1
Enabled breakpoint 1 at /Users/sammy/looping.py:7
(Pdb) clear 2
Deleted breakpoint 2 at /Users/sammy/looping.py:11
(Pdb)
Durma Noktalarının Ek İşlevsellikleri: Geçici Durma Noktaları: İlk tetiklenişte otomatik olarak silinir. Örneğin: tbreak 3 Şartlı Durma Noktaları: Belirli bir koşul sağlandığında durur. Örneğin: break looping.py:7, number > 500 Durma Noktası Komutları: Belirli bir durma noktasında özel komutlar çalıştırabilirsiniz. Örneğin: commands 1
Program Akışını Değiştirme
Python hata ayıklayıcısı, programınızın akışını çalışma zamanında jump
(atlama
) komutuyla değiştirmenize olanak tanır. Bu komut, bazı kodların çalışmasını engellemek için ileri atlamanızı sağlar veya kodu yeniden çalıştırmak için geri gitmenize olanak tanır.
Bu örnekte, sammy = 'sammy'
dizisinin içindeki harfleri listeye ekleyen küçük bir program üzerinde çalışacağız:
harf_listesi.py
def sammy_yazdir():
sammy_listesi = []
sammy = "sammy"
for harf in sammy:
sammy_listesi.append(harf)
print(sammy_listesi)
if __name__ == "__main__":
sammy_yazdir()
Programı her zamanki gibi python harf_listesi.py
komutuyla çalıştırırsak, aşağıdaki çıktıyı alırız:
Çıktı
['s']
['s', 'a']
['s', 'a', 'm']
['s', 'a', 'm', 'm']
['s', 'a', 'm', 'm', 'y']
Python hata ayıklayıcısını kullanarak, ilk döngüden sonra ileri atlamayı nasıl yapacağımızı gösterelim. Bunu yaparken, for döngüsünün kesildiğini fark edeceğiz:
python -m pdb harf_listesi.py
> /Users/sammy/harf_listesi.py(1)<module>()
-> def sammy_yazdir():
(Pdb) list
1 -> def sammy_yazdir():
2 sammy_listesi = []
3 sammy = "sammy"
4 for harf in sammy:
5 sammy_listesi.append(harf)
6 print(sammy_listesi)
7
8 if __name__ == "__main__":
9 sammy_yazdir()
10
11
(Pdb) break 5
Breakpoint 1 at /Users/sammy/harf_listesi.py:5
(Pdb) continue
> /Users/sammy/harf_listesi.py(5)sammy_yazdir()
-> sammy_listesi.append(harf)
(Pdb) pp harf
's'
(Pdb) continue
['s']
> /Users/sammy/harf_listesi.py(5)sammy_yazdir()
-> sammy_listesi.append(harf)
(Pdb) jump 6
> /Users/sammy/harf_listesi.py(6)sammy_yazdir()
-> print(sammy_listesi)
(Pdb) pp harf
'a'
(Pdb) disable 1
Disabled breakpoint 1 at /Users/sammy/harf_listesi.py:5
(Pdb) continue
['s']
['s', 'm']
['s', 'm', 'm']
['s', 'm', 'm', 'y']
Yukarıdaki hata ayıklama oturumunda, kodun devam etmesini engellemek için satır 5'e bir breakpoint (durma noktası) koyuyoruz, ardından kodu devam ettiriyor ve harf
değişkeninin değerlerini daha iyi görmek için pretty-print
komutuyla bazı değerleri yazdırıyoruz. Daha sonra, jump
komutunu kullanarak 6. satıra atlıyoruz. Bu noktada, harf değişkeni 'a' değerini alıyor, ancak o değeri sammy_listesi
listesine eklemiyoruz. Son olarak, breakpoint'i devre dışı bırakıp programı normal şekilde devam ettiriyoruz, böylece 'a' değeri sammy_listesi
listesine eklenmemiş oluyor.
Sonraki adımda, bu ilk oturumu sonlandırıp hata ayıklayıcıyı yeniden başlatabiliriz. Bu sefer, for döngüsünün ilk iterasyonunu yeniden çalıştıracağız:
> /Users/sammy/harf_listesi.py(1)<module>()
-> def sammy_yazdir():
(Pdb) list
1 -> def sammy_yazdir():
2 sammy_listesi = []
3 sammy = "sammy"
4 for harf in sammy:
5 sammy_listesi.append(harf)
6 print(sammy_listesi)
7
8 if __name__ == "__main__":
9 sammy_yazdir()
10
11
(Pdb) break 6
Breakpoint 1 at /Users/sammy/harf_listesi.py:6
(Pdb) continue
> /Users/sammy/harf_listesi.py(6)sammy_yazdir()
-> print(sammy_listesi)
(Pdb) pp harf
's'
(Pdb) jump 5
> /Users/sammy/harf_listesi.py(5)sammy_yazdir()
-> sammy_listesi.append(harf)
(Pdb) continue
> /Users/sammy/harf_listesi.py(6)sammy_yazdir()
-> print(sammy_listesi)
(Pdb) pp harf
's'
(Pdb) disable 1
Disabled breakpoint 1 at /Users/sammy/harf_listesi.py:6
(Pdb) continue
['s', 's']
['s', 's', 'a']
['s', 's', 'a', 'm']
['s', 's', 'a', 'm', 'm']
['s', 's', 'a', 'm', 'm', 'y']
Yukarıdaki hata ayıklama oturumunda, 6. satıra bir breakpoint ekledik ve ardından kodu devam ettirerek 5. satıra geri atladık. Bu esnada, harf değişkeninin 's' değerinin sammy_listesi
listesine iki kez eklendiğini görebiliyoruz. Daha sonra, 6. satırdaki breakpoint'i devre dışı bırakıp programı normal şekilde çalıştırıyoruz. Çıktıda, 's' değeri sammy_listesi
listesine iki kez eklenmiş görünüyor.
Bazı atlamalar, hata ayıklayıcı tarafından engellenir, özellikle belirli kontrol akışı ifadelerinden atlama yaparken. Örneğin, bir fonksiyona argümanlar tanımlanmadan atlayamazsınız veya bir try:except
bloğunun ortasına atlayamazsınız. Ayrıca, bir finally
bloğundan dışarı atlamak mümkün değildir.
Python hata ayıklayıcısındaki "jump" komutu, programınızı hata ayıklarken akışını değiştirmenize olanak tanır. Bu, akış kontrolünü farklı amaçlar için değiştirip değiştiremeyeceğinizi görmek veya kodunuzdaki sorunları daha iyi anlamak için faydalıdır.
Yaygın pdb Komutları Tablosu
Aşağıda, Python hata ayıklayıcısını kullanırken aklınızda tutmanız gereken bazı faydalı pdb
komutları ve kısa formaları yer almaktadır:
Komut | Kısa Form | Ne Yapar |
---|---|---|
args | a | Mevcut fonksiyonun argüman listesini yazdırır |
break | b | Programın belirli bir satırında durma noktası oluşturur (parametre gerektirir) |
continue | c veya cont | Program yürütmesini devam ettirir |
help | h | Komutlar listesi veya belirtilen komut için yardım sağlar |
jump | j | Bir sonraki yürütülecek satırı ayarlar |
list | l | Mevcut satır etrafındaki kaynak kodunu yazdırır |
next | n | Mevcut fonksiyonda bir sonraki satıra kadar devam eder |
step | s | Mevcut satırı çalıştırır ve ilk fırsatta durur |
pp | pp | İfadenin değerini güzel bir şekilde yazdırır |
quit veya exit | q | Programı sonlandırır |
return | r | Mevcut fonksiyon dönene kadar devam eder |
Hata ayıklayıcı ile ilgili komutlar ve nasıl çalıştığı hakkında daha fazla bilgiye Python hata ayıklayıcı dokümantasyonundan ulaşabilirsiniz.
Sonuç
Hata ayıklama, yazılım geliştirme projelerinin önemli bir aşamasıdır. Python hata ayıklayıcısı pdb
, yazdığınız Python programlarının her biriyle kullanabileceğiniz etkileşimli bir hata ayıklama ortamı sağlar.
Programınızı durdurma, değişkenlerinizin değerlerini inceleme ve program yürütmesini adım adım takip etme özellikleriyle, programınızın ne yaptığını daha iyi anlayabilir ve mantıksal hataları bulabilir veya bilinen sorunları çözebilirsiniz.
Lisa Tagliaferri tarafından yazılan How To Use the Python Debugger Program makalesinin düzenlenmiş çevirisi.
Daha Fazla Oku:
- Sonraki Makale: Python ile Etkileşimli Konsolda Hata Ayıklama
- Önceki Makale: Python 3'te Sınıflara Çok Biçimlilik (Polymorphism) Nasıl Uygulanır?