4. diel - PyCharm - Debugging
V minulej lekcii, PyCharm - Scopes, Live Templates, Databáza, Pluginy , sme sa zaoberali scopes, Live Templates, databázami a pluginy.
V dnešnom Python tutoriále si vysvetlíme, ako debugovať Python aplikácie za pomocou IDE PyCharm. Všetko si vyskúšame na jednoduchom príklade.
Debugging
O debuggingu, teda o procese odstránenia chýb v programe, sa niekedy hovorí aj ako o jeho "ladení". Chyby v programe sa väčšinou prejavujú tým, že je v nejakej premennej nesprávna hodnota, ktorá zapríčiní jeho nefunkčnosť. Určite ste sa už dostali do situácie, keď váš program nefungoval správne.Prečo a kedy debugovať?
Možno ste vykonávali zdĺhavé kontrolné výpisy rôznych premenných, aby ste zistili, kde je chyba. Chybu však možno odhaliť oveľa ľahšie, a to pomocou debugovania. Program preto najskôr spustíme v špeciálnom debugovacom režime, kde máme dovolené určité "cheaty", ako napr. program pozastavovať a nazerať do obsahu premenných.Pozor, nie je pravda, že debugujeme len keď program nefunguje. Naopak, používame ho čo najviac to ide, a to aj napríklad na kontrolu správnosti na kritických miestach.
Príklad - Krokovanie cyklu
Majme jednoduchý cyklus, v ktorom budeme vypisovať e-mailové adresy spojením mena a jednotnej koncovky napr.@abc.cz
:
{PYTHON}
jmena = ['anna', 'pavel', 'lucie']
for jmeno in jmena:
mail = jmeno + '@abc.cz'
print(mail)
Ako si môžeme overiť vyššie, program funguje korektne. Napriek tomu si ho skúsime oddebugovať, než sa pustíme na nefunkčný kód.
Breakpointy
Breakpoint je základný stavebný kameň pri debugovaní. Je to "bod" označujúci riadok, na ktorom sa program zastaví. Nám, ako programátorom, sa v tej chvíli zobrazí kompletný kontext programu, teda napr. čo je v tej chvíli kde uložené. Pretože program stojí, môžeme si všetko jednoducho skontrolovať.Pridanie breakpointu
Teraz sa naučíme vkladať breakpointy a zastavovať na nich program. V PyCharm sa breakpoint na daný riadok vkladá kliknutím do priestoru medzi číslom riadku a kódom (v editore). Breakpoint potom spoznáme podľa červeného kolieska a červeného riadku. Vložme teda breakpoint na riadok, kde sa vypisujú e-maily do konzoly (print(mail)
).
Debug režim
Breakpoint máme pridaný. Keď však program teraz spustíme, nič zvláštne sa nestane. Aby sa program naozaj zastavil, je potrebné ho spustiť v špeciálnom debugovacom režime. Na to slúži zelené tlačidlo Debug main (hneď vedľa zeleného tlačidla "Play"), na ktoré klikneme. Program sa následne spustí a zastaví sa, až narazí na náš breakpoint:Záložka Debug
Otvorila sa nová záložka Debug, ktorá obsahuje veľké množstvo informácií:Poďme si popísať, čo vidíme:
- Časť vyššie na obrázku, ohraničená zelene, obsahuje zoznam všetkých aktuálne viditeľných premenných a ich hodnoty.
- Žlto ohraničená časť obsahuje zásobník volaní všetkých funkcií, ktoré sa zavolali pred breakpointom.
- Ďalej sú na obrázku ešte červeno zvýraznené dve časti (ovládanie programu a breakpointov a krokovanie), ktoré si popíšeme v nasledujúcich podkapitolách.
Ovládanie programu a breakpointov
V prvej ohraničenej červenej časti (zvisle vľavo) sa nachádzajú tlačidlá pre kontrolu ovládania programu a breakpointov:- Rerun '(názov_súboru)' Ctrl + F5 - Ukončí aktuálny program a znovu ho spustí.
- Modify Run Configuration - Zobrazí nastavenie pre debug.
- Resume Program F9 - Uvoľní program z breakpointu a nechá program bežať a prípadne sa zastaví o ďalší breakpoint.
- Pause Program - Pozastaví vykonávanie vybraného vlákna - funguje podobne ako breakpoint, iba sa nezobrazia žiadne premenné.
- Stop '(názov_súboru)' Ctrl + F2 - Ukončí aktuálny program.
- View Breakpoints Ctrl + Shift + F8 - Zobrazí zoznam všetkých breakpointov.
- Mute Breakpoints - Potlačí všetky breakpointy. Keď program narazí na breakpoint v debug móde, breakpoint bude ignorovaný.
Krokovanie
V druhej červeno ohraničenej časti (vodorovne) sa nachádzajú tlačidlá pre krokovanie programu. Pomocou krokovania môžeme nechať program pokročiť na ďalší riadok a zase zastaviť:- Step Over F8 (krok cez) - Vykonáme ďalší krok cez daný riadok s breakpointom, na ktoré program aktuálne stojí. Pokiaľ sa na riadku volá funkcia, necháme ju len vykonať a potom prejdeme na ďalší riadok.
- Step Into F7 (krok do) - Vykonáme ďalší krok "do" daného riadku. Robí to isté čo Step Over až na rozdiel, že ak sa na riadku volá funkcia, prejdeme na prvý riadok vo funkcii.
- Step Into My Code Alt + Shift + F7 (vynútený krok do) - Vynúti prechod do funkcie na riadku aj v prípade, že nejde o našu metódu.
- Step Out Shift + F8 (krok von) - Pomocou kroku von vystúpime z aktuálne vykonávanej funkcie.
My sa nachádzame v cykle, kde iba postupne vypisujeme jednu hodnotu. Keď sa
pozrieme do výpisu konzoly, zatiaľ neuvidíme žiadny výpis (okrem možných
hlášok od IDE). Stlačením tlačidla Step Over (krok cez) sa
do konzoly vypíše prvá hodnota (v našom prípade prvý e-mail) a my sa v
programe dostaneme na riadok s for cyklom
(for jmeno in jmena:
). Keď tlačidlo Step Over
stlačíme znova, uvidíme v editore kódu posun na ďalšiu položku zoznamu,
pre ktorú sa zase vykoná blok kódu (do konzoly sa teda vypíše druhý
e-mail). Vykonáme ďalší krok cez daný riadok s breakpointom, na ktoré
program aktuálne stojí. Pokiaľ sa na riadku volá funkcia, necháme ju len
vykonať a potom prejdeme na ďalší riadok. Týmto spôsobom si môžeme
odkrokovať celý cyklus:
Príklad - Debugovanie programu
Nakoniec si dáme príklad naozaj na precvičenie debugovania. Máme napr. tieto dva vnorené cykly, ktoré by mali vypísať malú násobilku (0-9). Výstup by mal vyzerať takto:Konzolová aplikácia
0 0 0 0 0 0 0 0 0 0
0 1 2 3 4 5 6 7 8 9
0 2 4 6 8 10 12 14 16 18
0 3 6 9 12 15 18 21 24 27
0 4 8 12 16 20 24 28 32 36
0 5 10 15 20 25 30 35 40 45
0 6 12 18 24 30 36 42 48 54
0 7 14 21 28 35 42 49 56 63
0 8 16 24 32 40 48 56 64 72
0 9 18 27 36 45 54 63 72 81
Poblém ale je, že výstup po spustení programu vyzerá takto:
{PYTHON}
n = 10
for i in range(n):
for j in range(n):
print(i * i, end=" ")
print()
Chybu budeme chcieť nájsť a opraviť za pomoci breakpointov a krokovania. Aj keď je možné vidieť chybu na prvý pohľad, poďme si to spoločne odkrokovať. V zložitejších aplikáciách chyba takto ľahko vidieť nebude a proces debugovania bude nutný.
Postup riešenia príkladu
Breakpoint umiestnime na riadok s vonkajším for cyklom (for i in range(n):
) a spustíme program v debug režime.
Bude nás zaujímať, ako sa hodnoty inkrementujú. Tlačidlom
Step Into (krok do) budeme postupne prechádzať cez oba cykly
a pozorovať premenné i
a j
. Postupným krokovaním
zistíme, že vnútorný cyklus inkrementuje premenné i
a
j
správne (sledujeme postupne v editore kódu), ale výstupy v
konzole zodpovedajú iným hodnotám. Zameriame sa preto na
print()
, kde opravíme chybné i * i
na
i * j
a program už spustíme bez breakpointu. Výsledkom je
očakávaná malá násobilka čísel (0-9):
{PYTHON}
n = 10
for i in range(n):
for j in range(n):
print(i * j, end=" ")
print()
V budúcej lekcii, PyCharm - Pokročilý debugging , si rozšírime znalosti debugovania a zameriame sa na nástroje uľahčujúce celý proces.