Vead

Koodi käivitamisel võivad tekkida erindid (ingl. keeles Exception), mis võivad programmi töö peatada. Peatamisel teavitatakse kasutajat veast, kirjeldatakse mõjutatud rida ja veatüüpi. On oluline osata neid lugeda ja mõista.

Mõningate vigade puhul oskab Python öelda päris täpselt, et mis läks valesti, kuid sellegipoolest ei parandata ühtegi viga arendaja eest. Nii on see kõikides programmeerimiskeeltes, kuna interpretaator (ega ka kompilaator) ei tohi kunagi eeldada, et mida temalt soovitakse. Arvuti teeb täpselt seda, mida sa talle ütled.

Selline teoreetiline maailm, kus Python võib arendaja koodi omavoliliselt "parandada" võib esile tuua raskemini lahendatava mure - programm töötab, kuid tulemus on vale!

Vigade ehk erindite kinnipüüdmisest saab lugeda siin: Erindid (Exceptions).

Järgnev video tutvustab vigade mõistmist ja nende lahendamist:

`SyntaxError` Kõige lihtsam ja võib-olla tihedamini esinev viga on SyntaxError, mis näitab, et kuskil koodis on süntaksi viga. Rahvakeeli võib öelda, et tegemist on justkui kirjaveaga lauses.

# An example of a classic syntax error: the closing quotation mark is missing.
print("Hello world!)

Üleval oleva koodi käivitamise proovimisel saame süntaksivea, mis näitab meile vea kohta ja annab kaasa täpsustava sõnumi.

Traceback (most recent call last):
  File "<path to the file>", line 3
    print("Hello world!)
                       ^
SyntaxError: EOL while scanning string literal

Process finished with exit code 1

`IndentationError`

Python'is taanded on ka süntaksi osa ja nende vale kasutamine põhjustab kompileerimise vigu.

def func(a, b):
return a + b # --> IndentationError
Traceback (most recent call last):
  File "<path to the file>", line 3  # Number of line where the error occurred
    return a + b
         ^
IndentationError: expected an indented block

Process finished with exit code 1

Eelnev veateade kirjeldab, et esiletoodud rida asub ootamatul taandel.

`IndexError`

Tekib siis, kui indeks, mille järgi proovitakse saada elementi listist, ei ole korrektne.

some_list = ["Errors", "are", "sometimes", "better", "than", "no", "errors"]

print(some_list.__len__())  # --> 7

# There is no element in the list with such index
print(some_list[7])  # --> IndexError: list index out of range
Traceback (most recent call last):
  File "<path to the file>", line 4, in <module>
    print(some_list[7])
IndexError: list index out of range

`KeyError`

Sarnane IndexError veale, kuid siin puhul üritatakse otsida sõnastikust võtit, mida sõnastikus ei esine.

grades = {
    "english": 4,
    "math": 2,
    "physics": 3
    }

print(grades["geography"])  # --> KeyError
Traceback (most recent call last):
  File "test.py", line 7, in <module>
    print(grades["geography"])
KeyError: 'geography'

Veateade kirjeldab rida, kus antud viga ilmnes, ning toob välja ka võtme, mida prooviti. Sõnastike puhul on muidu olemas viis, kuidas vältida vea ilmnemist juhul, kui võtit ei ole.

grades = {
    "english": 4,
    "math": 2,
    "physics": 3
    }

print(grades.get("geography"))  # --> None

Antud juhul on tulemuseks None. Küll oleks mõistlik seda varianti kasutada ainult siis, kui mitte-leidmine on ettenähtud ning sinu ülejäänud kood oskab arvestada None tüüpi vastusega.

`NameError`

Tekib siis, kui proovitakse kasutada muutujat, mis ei olnud kunagi deklareeritud.

print(undeclared_variable + 10)  # --> NameError
Traceback (most recent call last):
  File "<path to the file>", line 2, in <module>
    print(undeclared_variable + 10)
NameError: name 'undeclared_variable' is not defined

`TypeError`

TypeError tähendab, kui üritatakse teha tegevusi kahe erineva tüübi vahel, mis kuidagi kokku ei käi. Tekib näiteks siis, kui proovitakse teha kahe muutuja liitmist, kus üks liidetavatest on sõne ja teine näiteks täisarv (int).

var = "10"

print(var + 10)  # --> TypeError: must be str, not int (cannot concatenate objects)
Traceback (most recent call last):
  File "<path to the file>", line 5, in <module>
    print(var + 10)
TypeError: must be str, not int

Veateadete mõistmine

Veateade annab meile järgmist informatsiooni:

  • kus tekkib viga (koodilõik ja rea number)

  • milline viga tekkis (IndexError vms)

  • täpsustav sõnum (näiteks string'ide liitmise korral, et üks liidetavatest ei ole string)

Olukord võib olla keerulisem juhul, kui näiteks meie kutsume funktsiooni, mis omakorda kutsub teise funktsiooni, kus tekkib viga. Vaatame, mis me saame väljundiks sellel juhul.

Olgu meil on selline kood

def third(a):
    print(int(a))  # Attempt to convert string <The output is called 'Stack Trace'> to int and print it out


def second(a, b):
    c = a + b
    print(c)  # --> The output is called 'Stack Trace'

    # Calling the third function
    third(c)


def first():
    # Calling the second function
    second("The output is called ", "'Stack Trace'")

first()

Selle kompileerimisel saame

Traceback (most recent call last):

  File "<path to the file>", line 18, in <module>
    first()

  File "<path to the file>", line 15, in first
    second("The output is called ", "'Stack Trace'")

  File "<path to the file>", line 10, in second
    first(c)

  File "<path to the file>", line 2, in third
    print(int(a))  # Attempt to convert string <The output is called 'Stack Trace'> to int and print it out

ValueError: invalid literal for int() with base 10: "The output is called 'Stack Trace'"

Väljundis on näha kogu protsessi, mille teostamisel tekkis viga. Ülevalt alla:

  1. Kompilaator märkas funktsiooni first() kutset ja läks sinna (rida 16, antud mooduli sees)

  2. Funktsioon first() omakorda kutsub teise funktsiooni, second() meie poolt määratud parameetritega (rida 13, funktsiooni first() sees)

  3. Funktsioon second() teeb stringi liitmist ja kutsub funktsiooni third() (rida 9, funktsiooni second() sees)

  4. Vea tekkimise koht: proovides teisendada argumenti a numbriks, saime ValueError: invalid literal for int() with base 10: "The output is called 'Stack Trace'"