Python pdb Modülü ile Debug Nasıl Yapılır?¶
Bu yazımızda python'da debugging(hata ayıklama) nasıl yapılır, temel komutlar nelerdir öğrenmeye çalışacağız. Debugging önemlidir çünkü kodunuzun beklendiği şekilde çalışmamasına neden olan hatanın tespit edilmesi ve çözüme kavuşturulması gereklidir. Python'daki dahili(built-in) modüllerden olan pdb modülü, debugging için gayet kullanışlı bir araçtır.
import pdb diyerek pdb'yi import ettikten sonra pdb.set_trace() fonksiyonunu çağırarak veya python3.7'den sonra gelen breakpoint() fonksiyonunu da kullanarak kodunuzun çalışmasını nerede duraklatmak ve hata ayıklamak istiyorsanız oraya ekleme yapabilirsiniz.
hello.py adında aşağıdaki gibi bir python dosyamız olsun. pdb'yi import edelim ve set_trace() fonksyionunu çağıralım
- Bu kodu python3 hello.py diyerek çalıştırıyorum ve terminalde/console'da neler olduğunu beraber görelim.dev@developers-MacBook-Pro pdb % python3 hello.py
> /Users/dev/webdev/snippets/pdb/hello.py(3)<module>()
-> print("Hello")
(Pdb)
n harfine basıp Enter diyerek (n)ext diyebiliriz. Böylece çalıştırılmaya hazır olan satır çalışacak ve bir sonraki satıra geçilecektir.
dev@developers-MacBook-Pro pdb % python3 hello.py
> /Users/dev/webdev/snippets/pdb/hello.py(3)<module>()
-> print("Hello")
(Pdb) n
Hello
> /Users/dev/webdev/snippets/pdb/hello.py(4)<module>()
-> print("Adnan")
dev@developers-MacBook-Pro pdb % python3 hello.py
> /Users/dev/webdev/snippets/pdb/hello.py(3)<module>()
-> print("Hello")
(Pdb) n
Hello
> /Users/dev/webdev/snippets/pdb/hello.py(4)<module>()
-> print("Adnan")
(Pdb) c
Adnan
is writing Python code.
dev@developers-MacBook-Pro pdb %
sample_main.py ve sample_helper.py adında 2 adet python dosyamız olsun. Bu dosyaların içeriği aşağıdaki gibidir.
sample_helper.py
def mysum(p1, p2):
print("computing start")
result = p1 * p2
print("Sum: ", result)
print("computing finish")
from simple_helper import mysum
if __name__ == "__main__":
print("main scope start")
mysum(1400, 53) # expected result 1453
print("main scope finish")
dev@developers-MacBook-Pro pdb % python3.11 simple_main.py
main scope start
computing start
Sum: 74200
computing finish
main scope finish
Gerçek hayatta büyük projelerin içerisinde geliştirme yaparken burda gördüğünüz gibi hatayı hemen fark edemeyebilirsiniz. Bu yanlış hesaplama yapan kodun büyük bir projeye ait olduğunu varsayalım ve hata ayıklama(debugging) yapalım.
simple_main.py içerisine breakpoint() ekliyorum (Not: import pdb; pdb.set_trace() diyerek de ekleme yapabilrdiniz.).
from simple_helper import mysum
if __name__ == "__main__":
breakpoint()
print("main scope start")
mysum(1400, 53) # expected result 1453
print("main scope finish")
dev@developers-MacBook-Pro pdb % python3.11 simple_main.py
> /Users/dev/webdev/snippets/pdb/simple_main.py(5)<module>()
-> print("main scope start")
(Pdb)
dev@developers-MacBook-Pro pdb % python3.11 simple_main.py
> /Users/dev/webdev/snippets/pdb/simple_main.py(5)<module>()
-> print("main scope start")
(Pdb) n
main scope start
> /Users/dev/webdev/snippets/pdb/simple_main.py(7)<module>()
-> mysum(1400, 53) # expected result 1453
(Pdb)
Bu satırda (n)ext ile devam edildiğinde fonksiyon çalıştırılacak ve böylece fonksiyondan çıkılacak. Bir sonraki satıra geçilecek. Bu satırda (s)tep ile devam edildiğinde fonksiyon --Call-- yani çağırılma işlemi başlayacak. Yani fonksiyonun içerisine gidilecek. Böylece fonksiyon çalıştırılıp çıkılmadan fonksiyon içerisindeki satırları tek tek çalıştırabileceğiz. (s)tep ile devam edelim
dev@developers-MacBook-Pro pdb % python3.11 simple_main.py
> /Users/dev/webdev/snippets/pdb/simple_main.py(5)<module>()
-> print("main scope start")
(Pdb) n
main scope start
> /Users/dev/webdev/snippets/pdb/simple_main.py(7)<module>()
-> mysum(1400, 53) # expected result 1453
(Pdb) s
--Call--
> /Users/dev/webdev/snippets/pdb/simple_helper.py(2)mysum()
-> def mysum(p1, p2):
(a)rguments ile fonksiyon parametrelerini(argüman) ve değerlerini görebilirsiniz veya direkt argüman isimlerini yazıp enter'a basarak değerlerini görebilirsiniz.
dev@developers-MacBook-Pro pdb % python3.11 simple_main.py
> /Users/dev/webdev/snippets/pdb/simple_main.py(5)<module>()
-> print("main scope start")
(Pdb) n
main scope start
> /Users/dev/webdev/snippets/pdb/simple_main.py(7)<module>()
-> mysum(1400, 53) # expected result 1453
(Pdb) s
--Call--
> /Users/dev/webdev/snippets/pdb/simple_helper.py(2)mysum()
-> def mysum(p1, p2):
(Pdb) a
p1 = 1400
p2 = 53
(Pdb) p1
1400
(Pdb) p2
53
--Call--
> /Users/dev/webdev/snippets/pdb/simple_helper.py(2)mysum()
-> def mysum(p1, p2):
(Pdb) a
p1 = 1400
p2 = 53
(Pdb) p1
1400
(Pdb) p2
53
(Pdb) l
1
2 -> def mysum(p1, p2):
3 print("computing start")
4 result = p1 * p2
5 print("Sum: ", result)
6 print("computing finish")
7
[EOF]
(Pdb)
(Pdb) ll
2 -> def mysum(p1, p2):
3 print("computing start")
4 result = p1 * p2
5 print("Sum: ", result)
6 print("computing finish")
(Pdb) n
> /Users/dev/webdev/snippets/pdb/simple_helper.py(3)mysum()
-> print("computing start")
(Pdb)
computing start
> /Users/dev/webdev/snippets/pdb/simple_helper.py(4)mysum()
-> result = p1 * p2
Kodda bulunduğunuz yeri tekrar hatırlamak için (w)here komutunu kullanabilirsiniz.
(Pdb) w
/Users/dev/webdev/snippets/pdb/simple_main.py(7)<module>()
-> mysum(1400, 53) # expected result 1453
> /Users/dev/webdev/snippets/pdb/simple_helper.py(4)mysum()
-> result = p1 * p2
(Pdb) w
/Users/dev/webdev/snippets/pdb/simple_main.py(7)<module>()
-> mysum(1400, 53) # expected result 1453
> /Users/dev/webdev/snippets/pdb/simple_helper.py(4)mysum()
-> result = p1 * p2
(Pdb) dict_defined_while_debugging = {"name":"adnan", "surname":"kaya", "hire-status":"open to work on upwork", "role":"Python Web Developer", "skills":"python, django, flask, scrapy, docker, tkinter, linux"}
(Pdb) pp dict_defined_while_debugging
{'hire-status': 'open to work on upwork',
'name': 'adnan',
'role': 'Python Web Developer',
'skills': 'python, django, flask, scrapy, docker, tkinter, linux',
'surname': 'kaya'}
(Pdb)
(Pdb) l
1
2 def mysum(p1, p2):
3 print("computing start")
4 -> result = p1 * p2
5 print("Sum: ", result)
6 print("computing finish")
7
[EOF]
(Pdb) b 6
Breakpoint 1 at /Users/dev/webdev/snippets/pdb/simple_helper.py:6
(Pdb) b
Num Type Disp Enb Where
1 breakpoint keep yes at /Users/dev/webdev/snippets/pdb/simple_helper.py:6
Pdb) ll
2 def mysum(p1, p2):
3 print("computing start")
4 -> result = p1 * p2
5 print("Sum: ", result)
6 B print("computing finish")
Not: Ayrıca b module:satır_no diyerek istediğimiz bir modülün istediğimiz satırına breakpoint koyabiliriz.
Hata aldığımız satırı ve yanlış matematiksel operatörü( + yerine * ) gördüğümüze göre debugging durumundan çıkıp kodu düzeltebiliriz.
(q)uit diyerek çıkabilirsiniz veya ©ontinue diyerek kodun çalışmasını ve programın sonlandırılmasını sağlayabilirsiniz. Veya geçici süreliğine (n)ext dedikten ve 4. satırı çalıştırdıktan sonra result = p1 + p2 diyerek elle yazıp Enter'a bastıktan sonra bulunduğunuz debugging ortamında result'u manipüle ederek çıktının sonucunu görebilirsiniz. Bunu deneyelim
(Pdb) n
computing start
> /Users/dev/webdev/snippets/pdb/simple_helper.py(4)mysum()
-> result = p1 * p2
(Pdb) n
> /Users/dev/webdev/snippets/pdb/simple_helper.py(5)mysum()
-> print("Sum: ", result)
(Pdb) result = p1 + p2
(Pdb) n
Sum: 1453
> /Users/dev/webdev/snippets/pdb/simple_helper.py(6)mysum()
-> print("computing finish")
(Pdb) c
computing finish
main scope finish
Bu şekilde inceleme, manipüle etme gibi operasyonlar gerçekleştirerek hata ayıklama işlemlerini projelerinizde gerçekleştirebilirsiniz.
Daha fazla bilgi edinmek için https://docs.python.org/3/library/pdb.html modülünü okuyabilirsiniz. Ek olarak https://pypi.org/project/ipdb/ python paketini de incelemek ve kullanmak isteyebilirsiniz.