Debuggern

Att använda och känna till rätt verktyg

Just nu räcker print(). Du lägger till en rad, kör programmet, ser vad variabeln innehåller. Den tekniken har ett namn, print-felsökning, och det är den vanligaste som finns: du lägger till en print() där du är osäker och läser av vad ett värde faktiskt var just där. Den är snabb, kräver inga verktyg, och du växer aldrig ur den helt. För ett tio raders skript är det precis rätt verktyg. Poängen med den här lektionen är inte att print() är fel. Poängen är att det finns ett bättre alternativ, och att du ska känna till det innan du faktiskt behöver det.

debugging [de-buhg-ing] verb.

  1. att vara detektiven i en kriminalfilm där du också är mördaren.

Filipe Fortes, 2013

Skämtet är gammalt bland programmerare och det sitter, för det säger felsökningens första sanning: buggen är nästan alltid din egen kod.

En Debugger Ett verktyg som låter dig köra ett program i kontrollerad takt, pausa det, stega igenom det rad för rad och inspektera alla variablers värden i realtid. Se: Debuggern är ett verktyg som låter dig pausa ett program mitt under körning och titta in i det. Du väljer en rad i koden, en brytpunkt, och när programmet når den raden stannar det. Du kan sedan stega framåt rad för rad och se varje variabels värde, exakt som de ser ut i minnet vid det ögonblicket.

Det fulla värdet av debuggern ser du nog inte idag. Program som är tio rader är inte tillräckligt komplexa, du behöver inte pausa dem för att förstå dem. Men när du längre fram bygger loopar som upprepar sig hundra gånger, eller hoppar in och ut ur funktioner med egna lokala variabler, kommer du tillbaka hit. Och då kommer du förhoppningsvis minnas att du visste hur det fungerade.

Vad en brytpunkt är

En Brytpunkt (breakpoint) En markering på en specifik rad som talar om för debuggern att pausa körningen innan den raden utförs. Sätts ut i VS Code genom att klicka i fältet till vänster om radnumren. Se: Debuggern (breakpoint) är en markering i koden som talar om för debuggern var den ska stanna. Du sätter ut den i VS Code genom att klicka i det grå fältet till vänster om radnumren. En prick dyker upp som bekräftelse, färgen beror på ditt färgtema, ofta röd eller orange.

Det är allt. Du har inte ändrat koden, bara sagt till verktyget: stanna här nästa gång du passerar den här raden.

namn = "Flisan"
ålder = 25
är_vinnare = True

print(namn)
print(ålder)
print(är_vinnare)
Pricken i vänstermarginalen är brytpunkten. Här sitter den på rad 2.

Sätter du ut en brytpunkt på rad 2 och startar debuggern kör Python rad 1 normalt, och stannar sedan precis innan rad 2 utförs. namn finns nu i Variables-panelen. ålder finns inte ännu. Det är exakt vad vi pratat om i Lådor i RAM & datatyper: variabeln existerar inte förrän Python passerat tilldelningsraden och skrivit värdet till minnet.

Debuggerns kontroller

När programmet är pausat har du fyra knappar i verktygsfältet som styr vad som händer härnäst. Två av dem behöver du nu:

Continue (F5) låter programmet köra vidare i full hastighet tills det når nästa brytpunkt, eller tills programmet är klart. Trycker du Continue utan fler brytpunkter kör programmet klart som vanligt.

Step Over (F10) kör exakt en rad och stannar igen. Det är det du använder när du vill se programmet röra sig rad för rad och se Variables-panelen uppdateras efter varje steg. Namnet Step Over syftar på att om raden anropar en funktion hoppar debuggern över funktionens inre kod, den kör den, men du ser inte vad som händer inuti. Det återkommer vi till i Anropsstacken, där Step Into (F11) plötsligt blir intressant.

Variables-panelen

Det är här det händer. Variables-panelen En vy i VS Codes debugger-läge som visar alla variabler som för tillfället finns i minnet, med deras namn, värden och typer. Uppdateras efter varje steg. Se: Debuggern i debugger-vyn visar varje variabel som för tillfället finns i minnet: dess namn, dess värde och dess typ, allt på en gång, uppdaterat efter varje steg.

Det är en sak att läsa att ålder = 25 skapar ett heltal i RAM. Det är en annan sak att stega förbi den raden och se ålder: 25 (int) dyka upp i panelen ur ingenting. Teorin och verkligheten möts.

Starta debuggern i VS Code

Debuggern i VS Code startas på flera sätt. Det enklaste är att trycka F5, VS Code frågar vilket program du vill köra om det inte redan vet det. Välj Python File så kör den den aktiva filen. Den längre vägen är att klicka på Run -> Start Debugging i menyn. Första gången VS Code ber dig välja en körmiljö, välj Python Debugger och sedan Python File.

Se det hända en gång

Öppna variabler.py, filen du skapade i Lådor i RAM & datatyper, och sätt en brytpunkt på rad 1. Startar du med F5 stannar programmet direkt, och Variables-panelen är tom. Det är hela poängen med den här delen i en bild: koden finns, men ingenting har hänt ännu.

Stega sedan med F10. Variablerna dyker upp en i taget, i exakt den ordning tilldelningarna står i filen, och de gör det först när du passerat raden. Uppgiften nedan gör om samma sak på ett program där värdena är annorlunda vid varje körning, och det är där debuggern börjar löna sig.

Uppgift: Stega igenom slumpen

Skapa filen debug_ovning.py med följande kod, tärningsduellen från Slump & moduler, fast utan sitt vägval:

import random

ditt_slag = random.randint(1, 6)
datorns_slag = random.randint(1, 6)
summa = ditt_slag + datorns_slag

print("Alea iacta est!")
print(f"Du: {ditt_slag}, datorn: {datorns_slag}, totalt: {summa}")

Utropet är latin: tärningen är kastad. Enligt legenden var det Julius Caesars ord när han korsade floden Rubicon med sin armé, beslutet som inte gick att ångra. Det är inte sista gången Caesar dyker upp i den här kursen.

  1. Sätt ut en brytpunkt på raden där ditt_slag tilldelas och starta debuggern med F5.

  2. Stega med F10 och se slumpvärdena dyka upp i Variables-panelen, ett i taget. Skriv ned vilka värden just den här körningen fick.

  3. Starta om debuggern och stega igen. Jämför med dina nedskrivna värden. Det är det här debuggern ger dig när slumpen är inblandad: du ser exakt vilka värden den aktuella körningen fick, något en omkörning aldrig kan visa i efterhand.

  4. Byt raden datorns_slag = random.randint(1, 6) mot datorns_slag = "6". Kör debuggern igen och stega långsamt. Vilken typ visar Variables-panelen för datorns_slag, och på exakt vilken rad kraschar programmet?

  5. Rätta felet, kör en sista gång, och pusha filen via Source Control-panelen.

Vad händer om

Flytta brytpunkten till raden print("Alea iacta est!") och starta om debuggern. Vilka variabler finns i Variables-panelen när programmet pausar, och varför?

Motivera & reflektera

Motivera när du skulle välja debuggern framför en print(). Vad ger Variables-panelen dig som print() inte lika enkelt kan visa, särskilt när värdena ändras vid varje körning?