Debugowanie za pomocą print()
Na początek zastosujmy najprostszą formę debugowania stosowaną przez najstarszych Indian😂
Printowanie, czyli wypisywanie stanu
Wypisywanie na konsolę wiadomości można nazwać pierwszą strategią mającą na celu poznanie stanu programu w danym momencie. Możemy to nazwać taką bardzo prymitywną (i wciąż bardzo szeroko stosowaną) formą debugowania.
W Pythonie użyjemy funkcji print()
, która wypisze nam dowolny tekst na konsolę uruchomieniową. Przykładem użycia print()
może być opis poszczególnych bloków programu. Usprawnijmy nasz kod o takie opisy:
# Cats inventory advanced manager print("Starting program") print("Preparing data") cat1 = "Kitty" cat2 = "Pussy" cat3 = "Paw" print("Initialising cats list") cats = [] print("Adding cats to list") cats.append(cat1) cats.append(cat2) cats.append(cat3) print("Returning list") print(cats)
Uruchamiamy ponownie program i tym razem widzimy taki oto wynik:
C:\Projects\cattify\venv\Scripts\python.exe C:/Projects/cattify/cats_main.py Starting program Preparing data Initialising cats list Adding cats to list Returning list ['Kitty', 'Pussy', 'Paw'] Process finished with exit code 0
Ok. Już wiemy więcej o wykonaniu programu i jego poszczególnych blokach… niby nie daje nam to zbytniej pomocy. Czy na pewno? Wykonajmy proste ćwiczenie.
Psujemy program
Celowo wprowadźmy błąd w postaci odniesienia do nieistniejącego kota. Zrobimy to dla linii:
cats.append(cat2)
Zmień ją na:
cats.append(cat233)
Następnie uruchom program. Powinieneś otrzymać taki wynik:
C:\Projects\cattify\venv\Scripts\python.exe C:/Projects/cattify/cats_main.py Traceback (most recent call last): File "C:/Projects/cattify/cats_main.py", line 14, in <module> cats.append(cat233) NameError: name 'cat233' is not defined Starting program Preparing data Initialising cats list Adding cats to list Process finished with exit code 1
No jest błąd (w PyCharm powinieneś zobaczyć sporo czerwonego tekstu)… Zaczynając od końca. Zauważ, że na końcu ostatniej linii mamy exit code 1
, co zdecydowanie oznacza niepoprawne zakończenie programu🤕
Następnie idąc w górę trafiamy na linię:
Adding cats to list
Hmm przejdźmy do kodu gdzie wpisujemy Adding cats to list
. Kolejne kroki w naszym programie, które printujemy:
print("Returning list") print(cats)
nie zostały wykonane. Czyli problem leży gdzieś pomiędzy ostatnim wyprowadzonym na konsolę printem a wiadomością, która nie została wypisana.
Miejsce problemu wydedukowane na podstawie printów:
AHA! Już mogę podejrzewać gdzie jest błąd!
Dzięki naszym printom wiem do jakiego momentu wykonał się nasz program. I mniej więcej potrafimy określić jaka część programu działa poprawnie.
Oczywiście informacja o błędzie na naszej konsoli:
Traceback (most recent call last): File "C:/Projects/cattify/cats_main.py", line 14, in <module> cats.append(cat233) NameError: name 'cat233' is not defined
Mówi nam dokładnie, że błąd jest w line 14
oraz jaka jest prawdopodobna przyczyna problemów. Jednak to nie dyskwalifikuje naszych printów.
Za pomocą printów posiadamy informacje dodatkowe o tym co zostało zrealizowane i łatwiej nam się jest odnaleźć w obszarze gdzie wystąpił błąd.
Wypisujemy wartości
Kolejnym krokiem może być wypisanie wartości. W naszym przypadku mamy problem z listą. Dodajmy więc dodatkowe informacje w formie kodu:
print(f'cats list contains: {cats}')
W ten sposób wypiszemy zawartość listy, poprzedzonej opisem do jakiej zmiennej należy zawartość.
Zrobimy taki print dla każdej modyfikacji listy. Czyli w kodzie może to wyglądać tak:
# Cats inventory advanced manager print("Starting program") print("Preparing data") cat1 = "Kitty" cat2 = "Pussy" cat3 = "Paw" print("Initialising cats list") cats = [] print(f'cats list contains: {cats}') print("Adding cats to list") cats.append(cat1) print(f'cats list contains: {cats}') cats.append(cat233) print(f'cats list contains: {cats}') cats.append(cat3) print(f'cats list contains: {cats}') print("Returning list") print(cats)
Uruchomimy teraz nasz program. Wynik to:
C:\Projects\cattify\venv\Scripts\python.exe C:/Projects/cattify/cats_main.py Traceback (most recent call last): File "C:/Projects/cattify/cats_main.py", line 16, in <module> cats.append(cat233) NameError: name 'cat233' is not defined Starting program Preparing data Initialising cats list cats list contains: [] Adding cats to list cats list contains: ['Kitty'] Process finished with exit code 1
Tutaj już bez problemu możemy przeczytać, że główny problem nastąpił gdzieś po dodaniu pierwszego kota 'Kitty'
do listy. Możemy też przypuszczać, że przyczyna problemu tkwi w linii w, której do listy dodajemy zmienną z kolejnym kotem😾 Tym samym jeszcze bardziej zawęziliśmy obszar problemów.
Logowanie to osobny, niezwykle ważny temat. Z dobrych logów możemy rozszyfrować przyczynę błędu i zaawansowane debugowanie będzie wtedy znacznie efektywniejsze a czasami nawet niepotrzebne.
Naprawiamy i podziwiamy
Pozostało nam teraz tylko poprawić zepsutą linię:
cats.append(cat233)
Na poprawną:
cats.append(cat2)
I uruchomić program, dzięki czemu zobaczymy dość dokładny opis kroków programu i wartości listy:
Starting program Preparing data Initialising cats list cats list contains: [] Adding cats to list cats list contains: ['Kitty'] cats list contains: ['Kitty', 'Pussy'] cats list contains: ['Kitty', 'Pussy', 'Paw'] Returning list ['Kitty', 'Pussy', 'Paw']
No dobra, tak sobie prymitywnie podebugowaliśmy ale chyba nie będziemy wszędzie tych printów wrzucać? Na dłuższą metę byłoby to męczące. Wyobraź sobie, że będziemy mieć bardzo dużo różnych zmiennych – byłby niezły chaos z setkami printów w kodzie..
Dlatego poznamy bardziej zaawansowaną strategię debugowania a pomoże nam w niej potężne narzędzie, które otrzymujemy razem z PyCharmem.