10 běžných typů chyb Pythonu a jak je vyřešit

Jako vývojáři softwaru se při tvorbě programů nevyhnete chybám. Ty se mohou lišit od nedostatků v logice, které vedou k neočekávaným výsledkům, přes chyby vzniklé porušením pravidel programovacího jazyka, až po problémy, které se objeví při samotném spuštění vašeho kódu. Tyto problémy se obecně označují jako chyby (anglicky „errors“).

Chyby jsou běžnou součástí programování v jakémkoli jazyce, bez ohledu na to, jak snadné je se daný jazyk naučit nebo používat.

Například i v Pythonu, který je známý svou čitelností a expresivní syntaxí, a je považován za relativně snadný na učení i používání ve srovnání s jinými programovacími jazyky, se programátorským chybám nevyhnete.

Vzhledem k tomu, že se chybám nelze vyhnout, je užitečné se seznámit s různými typy chyb, které se mohou objevit, a s tím, jak k nim dochází. To vám pomůže minimalizovat jejich výskyt během programování a také vám dá nástroje, jak s nimi efektivně pracovat, když nastanou.

Níže uvádíme některé z běžných chyb, se kterými se můžete setkat při programování v Pythonu:

Chyby syntaxe (SyntaxErrors)

Chyba syntaxe se objeví, když váš kód porušuje pravidla syntaxe daného programovacího jazyka. To má za následek neplatný řádek kódu.

Například v Pythonu je při tisku řetězce nutné jej uzavřít do uvozovek. Pokud tak neučiníte, dojde k chybě syntaxe.

Chyba syntaxe se může objevit také, pokud zapomenete otevírat nebo zavírat závorky (kulaté, hranaté nebo složené), pokud se překlepnete v klíčových slovech nebo názvech funkcí, pokud vynecháte dvojtečky na konci řídicích příkazů, nebo pokud ve výrazech chybí potřebné operátory.

Obecně platí, že k chybám syntaxe dochází, když nedodržíte pravidla, jak by měl být kód Pythonu napsán.

## Chyba syntaxe způsobená chybějícími uvozovkami kolem tištěného řetězce
print("Hello World)

age = 20
## Chyba syntaxe způsobená chybějící dvojtečkou v příkazu if
if age > 18
    print("Věk je nad 18")

## Chyba syntaxe, protože '(' nebyla nikdy uzavřena
def square(x:
    return x * x
print(square(4))

Po spuštění výše uvedeného kódu se zobrazí chybová zpráva, jak je uvedeno níže:

Chybová zpráva při spuštění kódu je následující:

  File "/home/madici/Desktop/helloworld.py", line 1
    print("Hello World)
          ^
SyntaxError: neukončený řetězcový literál (zjištěno na řádku 1)

Chcete-li tyto chyby opravit, použijte správnou syntaxi Pythonu, jak je uvedeno níže:

print("Hello World")

age = 20
if age > 18:
    print("Věk je nad 18")

def square(x):
    return x * x
print(square(4))

Chyby odsazení (IndentationError)

Na rozdíl od jiných jazyků, jako jsou Java, C nebo C++, které k oddělení bloků kódu používají složené závorky, Python používá k definování hierarchie a struktury bloků kódu odsazení. Například v Javě je veškerý kód, který se má provést po vyhodnocení podmínky, obsažen ve složených závorkách.

V Pythonu je však blok kódu definován odsazením. Typické odsazení v Pythonu se skládá ze čtyř mezer nebo jednoho tabulátoru. Na počtu mezer však nezáleží, pokud je odsazení konzistentní v celém kódu.

Jako programátor v Pythonu se pravděpodobně setkáte s chybami odsazení, když se vám nepodaří přidat požadované odsazení, například při psaní řídicích příkazů nebo funkcí, když použijete k vytvoření odsazení tabulátory i mezery (což může být pro interpret Pythonu matoucí), když vkládáte odsazení na nesprávném místě, nebo když vaše odsazení nejsou konzistentní v celém kódu.

Níže je uveden příklad kódu, který vede k chybě odsazení:

age = 20
if age > 18:
print("Věk je větší než 18")
   print("Můžete řídit")
else:
    print("Věk je menší než 18")

Chybové zprávy vyplývající z výše uvedeného kódu jsou uvedeny níže:

Chybová zpráva při spuštění kódu je následující:

  File "/home/madici/Desktop/helloworld.py", line 3
    print("Věk je větší než 18")
    ^
IndentationError: očekává se odsazený blok za příkazem 'if' na řádku 2

Chcete-li opravit tyto chyby, je nutné odsazení řádku za příkazem if a ujistěte se, že odpovídá odsazení ve zbytku kódu, jak je uvedeno níže:

age = 20
if age > 18:
   print("Věk je větší než 18")
   print("Můžete řídit")
else:
   print("Věk je menší než 18")

Chyby typu (TypeError)

V Pythonu je TypeError výjimka, která se objeví, když se pokusíte provést operaci s nekompatibilními datovými typy. Například, pokud se pokusíte sčítat řetězec a celé číslo nebo spojit (konkatenovat) řetězec s celým číslem, objeví se chyba TypeError.

S chybami typu TypeError se můžete setkat také, když používáte funkce nebo metody s nesprávnými datovými typy, když se pokoušíte použít neceločíselný index pro přístup k prvkům v seznamu nebo když se pokoušíte iterovat objektem, který nelze iterovat.

Obecně platí, že jakákoli operace s nesprávnými datovými typy povede k chybě TypeError.

Níže jsou uvedeny příklady operací, které mohou vést k chybám typu:

# Chyba typu vyplývající ze spojení (konkatenace) řetězce a celého čísla
age = 25
message = "Je mi " + age + " let."

list1 = [1, "hello", 5, "world", 18, 2021]
# Chyba typu způsobená nesprávným použitím vestavěných metod
print(sum(list1))

# Chyba typu způsobená sčítáním řetězce a celého čísla
num1 = 10
num2 = "16"
print(num1 + num2)

# Chyba typu způsobená použitím neceločíselného indexu
list2 = ["hello", "from", "the", "other", "side"]
print(list2["1"])

Chybové zprávy vyplývající z výše uvedeného kódu jsou uvedeny níže:

Ukázková zpráva TypeError z kódu je uvedena níže:

  File "/home/madici/Desktop/helloworld.py", line 3, in <module>
    message = "Je mi " + age + " let."
              ~~~~~~~~^~~~~
TypeError: lze spojovat (konkatenovat) pouze řetězec (ne "int") s řetězcem

Chcete-li odstranit chyby, použijte správné datové typy nebo provádějte převody typů, jak je uvedeno níže:

age = 25
message = "Je mi " + str(age) + " let."

list1 = [1, 5, 18, 2021]
print(sum(list1))

num1 = 10
num2 = "16"
print(num1 + int(num2))

list2 = ["hello", "from", "the", "other", "side"]
print(list2[1])

Chyby atributu (AttributeError)

V Pythonu se chyba AttributeError objeví, když se pokusíte použít atribut, který pro daný objekt neexistuje, nebo zavoláte metodu, která pro daný objekt neexistuje. AttributeError ukazuje, že objekt nemá atribut nebo metodu, která je volána.

Například, pokud zavoláte řetězcovou metodu na celé číslo, narazíte na AttributeError, protože metoda pro typ objektu, na kterém ji voláte, neexistuje.

V níže uvedeném příkladu je metoda capitalize(), která se používá k převodu prvního písmene řetězce na velké písmeno, volána na celé číslo. Výsledkem je chyba atributu, protože int nemá metodu capitalize().

# AttributeError způsobená voláním metody capitalize() na celočíselnou hodnotu
num = 1445
cap = num.capitalize()
print(cap)

Spuštění tohoto kódu má za následek chybovou zprávu uvedenou níže:

Zpráva AttributeError z kódu je následující:

  File "/home/madici/Desktop/helloworld.py", line 3, in <module>
    cap = num.capitalize()
          ^^^^^^^^^^^^^^
AttributeError: objekt 'int' nemá atribut 'capitalize'

Chcete-li vyřešit chybu AttributeError, ujistěte se, že metoda nebo atribut, který voláte, existuje pro typ objektu, na kterém ji voláte. V tomto případě tuto chybu vyřeší volání capitalize() na datovém typu řetězec, jak je uvedeno níže:

Chyby importu (ImportError)

Chyba importu v Pythonu nastane, když se pokusíte importovat modul, který nelze najít nebo není dostupný ve vašem aktuálním prostředí. Je možné, že modul ještě není nainstalován, nemáte správně nakonfigurovanou jeho cestu nebo jste modul, který se snažíte importovat, špatně napsali.

Chyba ImportError má jednu podtřídu s názvem ModuleNotFoundError, což je chyba, která je vyvolána při pokusu o import modulu, který nelze najít.

Například níže uvedený kód se pokouší importovat knihovnu pro analýzu dat pandas, což vyvolá takovou chybu, protože modul ještě není nainstalován.

Vygenerovaná zpráva ImportError je zobrazena níže:

  File "/home/madici/Desktop/helloworld.py", line 1, in <module>
    import pandas
ModuleNotFoundError: Modul s názvem 'pandas' nebyl nalezen

Chcete-li takovou chybu vyřešit, ujistěte se, že jsou moduly, které se pokoušíte importovat, nainstalovány. V případě, že to chybu nevyřeší, zkontrolujte, zda používáte správný pravopis modulu a správnou cestu k souboru pro přístup k modulu.

Chyby hodnoty (ValueError)

Toto je výjimka, která se objeví, když funkce v Pythonu obdrží hodnotu správného datového typu, ale tato hodnota je nevhodná. Například funkce Math.sqrt(), která se používá k nalezení druhé odmocniny číselných hodnot, vrátí ValueError, pokud zadáte záporné číslo.

I když bude hodnota správného typu, tedy číselné hodnoty, záporná hodnota z ní činí nevhodnou pro tuto operaci.

Funkce int(), která převádí číslo nebo řetězec, vrátí ValueError, pokud zadáte řetězec, který není číselnou hodnotou řetězce. Předání „123“ nebo „45“ funkci nezpůsobí žádnou chybu, protože řetězce lze převést na příslušnou celočíselnou hodnotu.

Pokud však zadáte řetězec, který není číselnou hodnotou řetězce, například „Ahoj“, vrátí ValueError. Důvodem je, že „Ahoj“, i když je řetězec, je nevhodný, protože nemá celočíselný ekvivalent.

Níže je uveden příklad kódu, který generuje ValueError:

# Chyba hodnoty způsobená nevhodnou celočíselnou hodnotou ve sqrt()
import math
num = -64
root = math.sqrt(num)
print(root)

# Chyba hodnoty způsobená předáním řetězce bez celočíselného
# ekvivalentu do funkce int()
numString = "Ahoj"
num = int(numString)
print(num)

Chyby z výše uvedeného kódu jsou uvedeny níže:

Vygenerovaná chybová zpráva je následující:

  File "/home/madici/Desktop/helloworld.py", line 4, in <module>
    root = math.sqrt(num)
           ^^^^^^^^^^^^^^
ValueError: chyba matematické domény

Chcete-li chybu opravit, použijte vhodné hodnoty ve funkcích, jak je uvedeno níže:

import math
num = 64
root = math.sqrt(num)
print(root)

numString = "5231"
num = int(numString)
print(num)

Chyby vstupu/výstupu (IOError)

IOError (Input/Output Error) je výjimka, která se objeví, když selže vstupní nebo výstupní operace. Může to být způsobeno pokusem o přístup k neexistujícímu souboru, nedostatečným místem na disku vašeho zařízení, pokusem o přístup k souboru, ke kterému nemáte dostatečná oprávnění, nebo při pokusu o přístup k souboru, který je právě používán jinými operacemi.

Takovou chybu pravděpodobně způsobí metody jako open(), read(), write() a close(), které se obvykle používají při práci se soubory.

Zvažte níže uvedený kód, který se pokouší otevřít soubor s názvem „notes.txt“, který neexistuje. Výsledkem kódu je IOError, která vyvolá FileNotFoundError:

S následující chybovou zprávou:

  File "/home/madici/Desktop/helloworld.py", line 2, in <module>
    file1 = open("notes.txt", "r")
            ^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] Žádný takový soubor nebo adresář: 'notes.txt'

Abyste předešli výše uvedené chybě, vše, co musíte udělat, je zajistit, aby v adresáři, ve kterém spouštíte terminál, existoval soubor „notes.txt“. Dalším způsobem, jak zpracovat IOErrors, je použití bloku try/except, jak je uvedeno níže:

Chyby jména (NameError)

NameError je výjimka, se kterou se setkáte, když se pokusíte použít proměnnou, funkci nebo modul, který neexistuje, není definován v aktuálním oboru nebo mu nebyla přiřazena hodnota.

K takové chybě obvykle dochází, když špatně napíšete názvy proměnných nebo funkcí, nebo je použijete před jejich definováním. Použití modulu bez jeho importu má za následek NameError.

Následující kód způsobí výjimku NameError:

# Chyba jména (NameError) vznikne, protože modul math nebyl importován
num = 64
root = math.sqrt(64)
print(root)

# Chyba jména vznikne, protože x je použito před definicí
y = 23
print(x)

#Chyba jména protože název funkce není definován
def greet():
    print("Dobré ráno")
great() #Chyba jména: název 'great' není definován

Z výše uvedeného kódu vyplývají následující chybové zprávy:

Ukázková zpráva NameError je zobrazena níže:

  File "/home/madici/Desktop/helloworld.py", line 3, in <module>
    root = math.sqrt(64)
           ^^^^
NameError: název 'math' není definován

Chcete-li takovou chybu NameError vyřešit, ujistěte se, že nepoužíváte moduly, dokud je neimportujete, že nepoužíváte proměnné nebo funkce dříve, než je definujete, a že se v názvech funkcí nebo proměnných nedopouštíte překlepů:

import math
num = 64
root = math.sqrt(64)
print(root)

y = 23
print(y)

def greet():
    print("Dobré ráno")
greet()

Chyby indexu (IndexError)

Chyba IndexError je výjimka, ke které dochází při pokusu o přístup k indexu v seznamu nebo n-tici, který je mimo rozsah. Zvažte níže uvedený seznam:

list1 = [1, 2, 3, 4, 5]

Seznam má pět prvků. Python počítá indexy od 0 (nuly). Proto má výše uvedený seznam indexy v rozsahu od 0 do n-1, přičemž n je počet prvků v seznamu. V tomto případě bude index seznamu v rozsahu od 0 do 4.

Pokud se pokusíte o přístup k prvku s indexem větším než 4, narazíte na chybu IndexError, protože index je mimo rozsah v seznamu, z něhož se pokoušíte získat prvek. Níže uvedený kód generuje IndexError:

list1 = [1, 2, 3, 4, 5]
item = list1[6] #IndexError protože index seznamu je mimo rozsah
print(item)

Chyba z kódu je zobrazena níže:

Vygenerovaná zpráva IndexError je následující:

  File "/home/madici/Desktop/helloworld.py", line 2, in <module>
    item = list1[6] #IndexError protože index seznamu je mimo rozsah
           ~~~~~^^^
IndexError: index seznamu je mimo rozsah

Nejlepším způsobem, jak se vyhnout chybě IndexError, je použít funkce range() a len(), abyste se ujistili, že přistupujete pouze k prvkům, které jsou v dosahu, jako je tento:

list1 = [1, 2, 3, 4, 5]

for i in range(len(list1)):
    print(list1[i])

Chyby klíče (KeyError)

KeyError je výjimka, ke které dochází, když se pokusíte o přístup k prvku ze slovníku pomocí klíče, který ve slovníku neexistuje. Zvažte níže uvedený slovník:

cities = {"Canada": "Ottawa", "USA": "Washington", "Italy": "Rome"}

Klíče ve slovníku jsou „Kanada“, „USA“, „Itálie“. K položkám ze slovníku měst se dostanete pomocí těchto tří klíčů. Pokud se však pokusíte o přístup k prvku pomocí klíče, který neexistuje, například „Brazílie“, narazíte na chybu KeyError, jak je uvedeno níže:

Vygenerovaná zpráva KeyError je zobrazena níže:

  File "/home/madici/Desktop/helloworld.py", line 6, in <module>
    print(cities["Brazil"])
          ~~~~~~^^^^^^^^^^
KeyError: 'Brazil'

Chcete-li vyřešit chybu KeyError, ujistěte se, že klíče, které používáte pro přístup k prvkům ve slovníku, jsou ve slovníku přítomny. Chcete-li to provést, můžete použít následující prohlášení:

cities = {"Canada": "Ottawa", "USA": "Washington", "Italy": "Rome"}

country = "Canada"

if country in cities:
    print("Hlavní město " + country + " je " + cities[country])
else:
	print("Klíč " + country + " se ve slovníku měst nenachází")

Tímto způsobem se vyhnete chybám KeyError při přístupu k prvkům ze slovníku.

Závěr

Při programování v Pythonu se bez ohledu na vaši úroveň odbornosti nevyhnete chybám. Proto se nezapomeňte seznámit s různými typy chyb popsanými v tomto článku, abyste si byli jisti, že je budete umět řešit, až nastanou.

Můžete si také prozkoumat některé užitečné Python jednorázové řádky (one-liners) pro zjednodušení běžných úkolů.