Vanliga Feltyper i Python och Hur Man Hanterar Dem
Som programmerare är det oundvikligt att stöta på fel under utvecklingen av mjukvara. Dessa kan vara allt från logiska fel som leder till oväntade resultat, till fel som uppstår genom att bryta mot de regler som gäller för ett visst programmeringsspråk, samt fel som dyker upp när programmet körs. Alla dessa fel kallas ofta för buggar.
Buggar är ett universellt fenomen som förekommer i alla programmeringsspråk, oavsett hur lättanvänt eller inlärningsvänligt språket är.
I Python, trots att språket lägger stor vikt vid läsbarhet och erbjuder en uttrycksfull syntax samt anses vara relativt enkelt att lära sig och använda jämfört med många andra programmeringsspråk, är du inte skyddad mot programmeringsfel när du jobbar med Python.
Eftersom fel är en oundviklig del av programmeringsprocessen, är det en bra strategi att lära sig om de olika typer av fel som kan uppstå och hur de uppkommer. Denna kunskap gör det möjligt för dig att undvika eller minimera fel under kodning och ger dig också verktygen för att hantera dem när de väl uppstår.
Här nedan listas några av de vanligaste Python-felen du kan stöta på när du programmerar med detta språk:
Syntaxfel
Ett syntaxfel uppstår när koden som skrivs bryter mot reglerna för det aktuella programmeringsspråket. Detta resulterar i en ogiltig kodrad.
I Python, till exempel, måste en sträng omges av citattecken när den ska skrivas ut. Om detta inte görs, resulterar det i ett syntaxfel.
Syntaxfel kan också uppstå om parenteser, hakparenteser eller klammerparenteser inte öppnas eller stängs korrekt, om nyckelord eller funktionsnamn stavas fel, om kolon saknas i slutet av flödeskontrollsatser eller om nödvändiga operatorer saknas i uttryck.
Sammanfattningsvis uppstår syntaxfel när någon av reglerna för hur Python-kod ska skrivas bryts.
## Syntaxfel på grund av saknade citattecken print("Hej världen) age = 20 ## Syntaxfel på grund av saknat kolon i en if-sats if age > 18 print("Åldern är över 18") ## Syntaxfel på grund av att '(' inte stängts def square(x: return x * x print(square(4))
När koden ovan körs, kommer ett felmeddelande som liknar följande att dyka upp:
Felmeddelandet som returneras när koden körs är som följer:
File "/home/madici/Desktop/helloworld.py", line 1 print("Hej världen) ^ SyntaxError: unterminated string literal (detected at line 1)
För att lösa dessa fel måste Python-syntaxen användas korrekt, som visas nedan:
print("Hej världen") age = 20 if age > 18: print("Åldern är över 18") def square(x): return x * x print(square(4))
Indragningsfel
Till skillnad från språk som Java, C eller C++, som använder klammerparenteser för att definiera kodblock, använder Python indrag för att strukturera och definiera hierarkin i kodblock. I Java, till exempel, placeras all kod som ska exekveras när ett villkor har utvärderats inuti klammerparenteser.
I Python däremot, indenteras kodblocket. Vanligtvis används fyra blanksteg eller en tabulator för en indragning. Det exakta antalet mellanslag spelar ingen roll, så länge indragningen är konsekvent genom hela koden.
Som Python-programmerare kommer du sannolikt att stöta på indragningsfel om du misslyckas med att lägga till nödvändiga indrag, till exempel i kontrollsatser eller funktioner, om du blandar tabbar och mellanslag för indragning (vilket förvirrar tolken), eller om indragningarna är inkonsekventa genom koden.
Ett exempel på kod som resulterar i ett indragningsfel visas nedan:
age = 20 if age > 18: print("Åldern är större än 18") print("Du får köra bil") else: print("Åldern är mindre än 18")
Felmeddelandet som genereras av koden ovan visas här:
Felmeddelandet som genereras när koden körs är som följer:
File "/home/madici/Desktop/helloworld.py", line 3 print("Åldern är större än 18") ^ IndentationError: expected an indented block after 'if' statement on line 2
För att korrigera felet, krävs en indragning på raden efter if-satsen, och denna indragning måste matcha den indragning som används i resten av koden, som visas nedan:
age = 20 if age > 18: print("Åldern är större än 18") print("Du får köra bil") else: print("Åldern är mindre än 18")
Typfel
I Python uppstår ett TypeError när en operation försöker utföras med en inkompatibel datatyp. Om du till exempel försöker addera en sträng och ett heltal, eller sammanfoga en sträng med ett heltal, kommer ett TypeError att uppstå.
Typfel kan också uppstå om funktioner eller metoder används med felaktiga datatyper, om ett icke-heltalsindex används för att komma åt element i en iterabel, till exempel en lista, eller om det försöks iterera genom ett objekt som inte är iterabelt.
Generellt sett kommer varje operation som använder en inkompatibel datatyp att resultera i ett TypeError.
Här är några exempel på operationer som kan leda till Typfel:
# Typfel som uppstår vid sammanfogning av en sträng och ett heltal age = 25 message = "Jag är " + age + " år gammal." list1 = [1, "hej", 5, "världen", 18, 2021] #Typfel som uppstår vid felaktig användning av inbyggda metoder print(sum(list1)) #Typfel som uppstår vid addition av en sträng och ett heltal num1 = 10 num2 = "16" print(num1 + num2) #Typfel som uppstår vid användning av ett icke-heltalsindex list2 = ["hej", "från", "andra", "sidan"] print(list2["1"])
Felmeddelandena som genereras av koden ovan visas nedan:
Ett exempel på ett TypeError-meddelande från koden visas nedan:
File "/home/madici/Desktop/helloworld.py", line 3, in <module> message = "Jag är " + age + " år gammal." ~~~~~~~~^~~~~ TypeError: can only concatenate str (not "int") to str
För att åtgärda felen, använd korrekta datatyper eller typomvandlingar enligt nedan:
age = 25 message = "Jag är " + str(age) + " år gammal." list1 = [1, 5, 18, 2021] print(sum(list1)) num1 = 10 num2 = "16" print(num1 + int(num2)) list2 = ["hej", "från", "andra", "sidan"] print(list2[1])
AttributeError
I Python inträffar ett AttributeError när du försöker använda ett attribut som inte finns i ett objekt eller om en metod anropas som inte finns på det objektet den anropas på. Ett AttributeError indikerar att ett objekt saknar attributet eller metoden som anropas.
Till exempel, om du anropar en strängmetod på ett heltal, kommer ett AttributeError att uppstå eftersom metoden inte finns på den typen av objekt.
I exemplet nedan anropas metoden capitalize(), som konverterar den första bokstaven i en sträng till versal, på ett heltal. Detta leder till ett attributfel eftersom int-objekt inte har metoden capitalize().
# AttributeError som uppstår när capitalize() anropas på ett heltal num = 1445 cap = num.capitalize() print(cap)
Att köra den här koden resulterar i felmeddelandet nedan:
AttributeError-meddelandet från koden är följande:
File "/home/madici/Desktop/helloworld.py", line 3, in <module> cap = num.capitalize() ^^^^^^^^^^^^^^ AttributeError: 'int' object has no attribute 'capitalize'
För att lösa ett AttributeError, måste du säkerställa att metoden eller attributet som anropas faktiskt finns på det objektet som anropet görs på. I det här fallet löses felet genom att anropa capitalize() på en sträng:
ImportError
Importfelet i Python uppstår när du försöker importera en modul som antingen inte kan hittas eller som inte är tillgänglig i den aktuella miljön. Orsaker till detta kan vara att modulen inte är installerad, att dess sökväg inte är korrekt konfigurerad eller att modulnamnet är felstavat.
En underklass till ImportError är ModuleNotFoundError, som uppstår när en modul inte kan hittas.
Följande kod försöker importera dataanalysbiblioteket pandas, vilket resulterar i ett fel eftersom modulen inte är installerad.
ImportError-meddelandet som genereras visas nedan:
File "/home/madici/Desktop/helloworld.py", line 1, in <module> import pandas ModuleNotFoundError: No module named 'pandas'
För att lösa ett sådant fel, se till att de moduler som importeras är installerade. Om detta inte löser felet, kontrollera stavningen av modulnamnet och att sökvägen till modulen är korrekt.
ValueError
ValueError uppstår när en funktion i Python tar emot ett värde av rätt datatyp, men värdet i sig är olämpligt. Till exempel, funktionen Math.sqrt(), som används för att beräkna kvadratroten av ett numeriskt värde, kommer att returnera ett ValueError om ett negativt tal anges.
Värdet kommer att vara av rätt typ, ett numeriskt värde, men eftersom talet är negativt är det ett olämpligt värde för just denna funktion.
Funktionen int(), som konverterar ett tal eller en sträng, returnerar ett ValueError om en sträng som inte representerar ett numeriskt värde skickas till funktionen. Att skicka in strängarna ”123” eller ”45” orsakar inget fel eftersom de kan konverteras till heltal.
Men om en sträng som inte är ett numeriskt strängvärde skickas in, till exempel ”Hej”, kommer funktionen att returnera ett ValueError. Detta beror på att ”Hej”, även om det är en sträng, är ett olämpligt värde eftersom det inte har en heltalsekvivalent.
Här är ett exempel på kod som genererar ett ValueError:
# ValueError som uppstår på grund av olämpligt int-värde i sqrt() import math num = -64 root = math.sqrt(num) print(root) # ValueError som uppstår på grund av att en sträng som inte är ett tal skickas till int() numString = "Hej" num = int(numString) print(num)
Felmeddelandet som genereras visas nedan:
Felmeddelandet som genereras är följande:
File "/home/madici/Desktop/helloworld.py", line 4, in <module> root = math.sqrt(num) ^^^^^^^^^^^^^^ ValueError: math domain error
För att åtgärda felet, använd lämpliga värden i funktionerna, enligt nedan:
import math num = 64 root = math.sqrt(num) print(root) numString = "5231" num = int(numString) print(num)
IOFel
IOError (Input/Output Error) är ett undantag som uppstår när en in- eller utmatningsoperation misslyckas. Detta kan bero på att programmet försöker komma åt en fil som inte finns, att det inte finns tillräckligt med lagringsutrymme, att behörighet saknas för att komma åt en fil, eller om filen för tillfället används av en annan process.
Metoder som open(), read(), write() och close(), som ofta används vid filhantering, är de som vanligtvis orsakar ett sådant fel.
Följande kod försöker öppna en fil med namnet ”notes.txt” som inte finns. Detta resulterar i en IOError som genererar ett FileNotFoundError:
Med följande felmeddelande:
File "/home/madici/Desktop/helloworld.py", line 2, in <module> file1 = open("notes.txt", "r") ^^^^^^^^^^^^^^^^^^^^^^ FileNotFoundError: [Errno 2] No such file or directory: 'notes.txt'
För att undvika felet, se till att filen ”notes.txt” finns i katalogen där terminalen körs. Ett annat sätt att hantera IOError är att använda try except-blocket, som visas nedan:
Namnfel
NameError är ett undantag som uppstår när du försöker använda en variabel, funktion eller modul som inte finns, inte är definierad i det aktuella omfånget eller som inte har tilldelats ett värde.
Ett sådant fel uppstår vanligtvis om variabel- eller funktionsnamn stavas fel, om de används innan de definierats eller om en modul används utan att importeras.
Följande kod resulterar i ett NameError-undantag:
# NameError uppstår eftersom math-modulen inte har importerats num = 64 root = math.sqrt(64) print(root) # NameError uppstår eftersom x används innan det har definierats y = 23 print(x) #NameEror uppstår eftersom funktionsnamnet inte är definierat def greet(): print("God morgon") great() #ameError: name 'great' is not defined
Följande felmeddelanden är resultatet av koden ovan:
Ett exempel på ett NameError-meddelande visas nedan:
File "/home/madici/Desktop/helloworld.py", line 3, in <module> root = math.sqrt(64) ^^^^ NameError: name 'math' is not defined
För att lösa ett namnfel, se till att inga moduler används innan de importerats, att inga variabler eller funktioner används innan de definierats och att funktions- och variabelnamn är korrekt stavade:
import math num = 64 root = math.sqrt(64) print(root) y = 23 print(y) def greet(): print("God morgon") greet()
IndexError
Ett IndexError är ett undantag som uppstår när du försöker komma åt ett index i en lista eller tuppel som ligger utanför det giltiga intervallet. Tänk på listan nedan:
list1 = [1, 2, 3, 4, 5]
Listan har fem element. Python räknar index från 0 (noll). Därför har listan ovan index som sträcker sig från 0 till n-1, där n är antalet element i listan. I det här fallet varierar indexet i listan från 0 till 4.
Om du försöker komma åt ett element med ett index som är större än 4, kommer du att stöta på ett IndexError eftersom indexet då ligger utanför det tillåtna intervallet för listan. Följande kod genererar ett IndexError:
list1 = [1, 2, 3, 4, 5] item = list1[6] #IndexError eftersom listindexet är utanför intervallet print(item)
Felet från koden visas nedan:
IndexError-meddelandet som genereras är följande:
File "/home/madici/Desktop/helloworld.py", line 2, in <module> item = list1[6] #IndexError eftersom listindexet är utanför intervallet ~~~~~^^^ IndexError: list index out of range
Det bästa sättet att undvika ett IndexError är att använda funktionerna range() och len() för att säkerställa att du endast kommer åt element som ligger inom det giltiga intervallet, som visas nedan:
list1 = [1, 2, 3, 4, 5] for i in range(len(list1)): print(list1[i])
KeyError
Ett KeyError är ett undantag som uppstår när du försöker komma åt ett objekt från en ordbok med en nyckel som inte finns i ordboken. Tänk på ordboken nedan:
cities = {"Canada": "Ottawa", "USA": "Washington", "Italy": "Rom"}
Nycklarna i ordboken är ”Kanada”, ”USA” och ”Italien”. Du kan komma åt objekten i ordboken städer med dessa tre nycklar. Men om du försöker komma åt ett element med en nyckel som inte finns, till exempel ”Brasilien”, kommer du att stöta på ett KeyError, som visas nedan:
KeyError-meddelandet som genereras visas nedan:
File "/home/madici/Desktop/helloworld.py", line 6, in <module> print(cities["Brazil"]) ~~~~~~^^^^^^^^^^ KeyError: 'Brazil'
För att lösa ett KeyError, säkerställ att nycklarna du använder för att komma åt element i ordboken faktiskt finns i den. Du kan till exempel använda ett if…else-uttryck, som visas nedan:
cities = {"Canada": "Ottawa", "USA": "Washington", "Italy": "Rom"} country = "Canada" if country in cities: print("Huvudstaden i " + country + " är " + cities[country]) else: print("Nyckeln " + country + " finns inte i städernas ordbok")
På detta sätt undviker du att stöta på KeyError när du kommer åt element i en ordbok.
Slutsats
Oavsett din erfarenhetsnivå kommer du med all säkerhet att stöta på fel när du kodar i Python. Det är därför bra att bekanta sig med de olika typer av fel som lyfts fram i denna artikel för att du ska kunna hantera dem när de väl uppstår.
Du kan även utforska några användbara Python one-liners för att förenkla vanliga uppgifter.