10 уобичајених типова Питхон грешака и како их решити

Као програмер, неминовно ћете се сусрести са грешкама током процеса стварања софтвера. Оне се могу манифестовати на различите начине, од логичких пропуста који доводе до неочекиваних резултата, преко одступања од правила програмског језика, па све до грешака које се јављају при самом покретању програма. Ове ситуације се уобичајено називају грешкама.

Грешке су саставни део сваког програмског језика, без обзира на његову једноставност учења или употребе.

На пример, у Питону, иако је наглашена читљивост, коришћена је изражајна синтакса и сматра се релативно лаким за учење и употребу у поређењу са другим језицима, нисте имуни на грешке током програмирања у Питону.

С обзиром на то да су грешке неизбежне, добра стратегија је да се упознате са различитим врстама грешака које се могу појавити и начинима на које настају. Ово ће вам помоћи да избегнете или минимизирате ове грешке током процеса кодирања, а такође ћете бити спремни да се са њима носите када се појаве.

У наставку су наведене неке уобичајене Питон грешке на које можете наићи док кодирате:

Синтаксне грешке

Синтаксна грешка је она која се дешава када напишете код који крши правила програмског језика. Ово резултира неважећом линијом кода.

На пример, у Питону, приликом штампања ниске, она мора бити стављена између наводника. Игнорисање овог правила доводи до синтаксне грешке.

Синтаксна грешка такође може настати услед пропуштених отворених или затворених заграда, угластих или витичастих заграда, погрешно написаних кључних речи или имена функција, пропуштених двотача на крају контролних изјава, или када недостају неопходни оператори у изразима.

У принципу, синтаксне грешке се појављују када прекршите правила писања Питон кода.

## sintaksna greska zbog nedostajucih navodnika
## oko niske koja se stampa
print("Hello World)

age = 20
## Sintaksna greska zbog nedostajuce dvotacke u if naredbi
if age > 18
    print("Starost je preko 18")

## Sintaksna greska zato sto '(' nikad nije zatvorena
def kvadrat(x:
    return x * x
print(kvadrat(4))

Када покренете горњи код, појавиће се порука о грешци:

Порука о грешци приликом извршавања кода је следећа:

  File "/home/madici/Desktop/helloworld.py", line 1
    print("Hello World)
          ^
SyntaxError: unterminated string literal (detected at line 1)

Да бисте отклонили ове грешке, користите исправну Питон синтаксу, као што је приказано испод:

print("Hello World")

age = 20
if age > 18:
    print("Starost je preko 18")

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

Грешке увлачења

За разлику од других језика, попут Јаве, C или C++, који користе витичасте заграде за раздвајање блокова кода, Питон користи увлачење да дефинише хијерархију и структуру блокова кода. На пример, приликом писања контролних наредби у Јави, сав код који треба да се изврши након евалуације услова налази се унутар витичастих заграда.

У Питону, међутим, блок кода ће бити увучен. Стандардне увлаке у Питону се састоје од четири размака или једног табулатора. Важно је да се током целог кода доследно користи исти број размака.

Као Питон програмер, вероватно ћете се сусрести са грешкама увлачења када пропустите да додате потребно увлачење, на пример, приликом писања контролних изјава или функција, када користите и табулаторе и размаке за креирање увлачења, што збуњује интерпретер, када поставите увлаке на погрешно место, или када увлачење није доследно у вашем коду.

Пример кода који резултира грешком увлачења је приказан испод:

age = 20
if age > 18:
print("Starost je veća od 18")
   print("Možete da vozite")
else:
    print("Starost je manja od 18")

Поруке о грешци које произилазе из горњег кода су приказане у наставку:

Порука о грешци приликом извршавања кода је:

  File "/home/madici/Desktop/helloworld.py", line 3
    print("Starost je veća od 18")
    ^
IndentationError: expected an indented block after 'if' statement on line 2

Да бисте исправили грешке, потребно је увући линију након if наредбе, и обезбедити да се подудара са увлачењем у остатку кода, као што је приказано испод:

age = 20
if age > 18:
   print("Starost je veća od 18")
   print("Možete da vozite")
else:
   print("Starost je manja od 18")

Грешке типа

У Питону, TypeError је изузетак који се јавља када покушате да извршите операцију користећи некомпатибилан тип података. На пример, ако покушате да саберете ниску и цео број или спојите низ са целим бројем, појавиће се TypeError.

Такође се можете сусрести са TypeError-има када користите функције или методе са погрешним типовима података, када покушате да користите нецелобројни индекс за приступ елементима у итераблима, попут листе, или када покушате да итерирате кроз објекат који није итерабилан.

У принципу, свака операција која користи неисправан тип података довешће до TypeError-a.

Примери операција које могу довести до TypeError-а су приказани у наставку:

# TypeError zbog spajanja niske i celog broja
age = 25
message = "Imam " + age + " godina."

list1 = [1, "zdravo", 5, "svete", 18, 2021]
#Type errors zbog pogresne upotrebe ugradjenih metoda
print(sum(list1))

#TypeError zbog sabiranja niske i celog broja
num1 = 10
num2 = "16"
print(num1 + num2)

#TypeError zbog koriscenja necelobrojnog indeksa
list2 = ["zdravo", "iz", "druge", "strane"]
print(list2["1"])

Поруке о грешкама које произилазе из горњег кода су приказане у наставку:

Пример поруке TypeError из кода је приказан у наставку:

  File "/home/madici/Desktop/helloworld.py", line 3, in 
    message = "Imam " + age + " godina."
              ~~~~~~~~^~~~~
TypeError: can only concatenate str (not "int") to str

Да бисте уклонили грешке, користите исправне типове података или конверзије типа, као што је приказано у наставку:

age = 25
message = "Imam " + str(age) + " godina."

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

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

list2 = ["zdravo", "iz", "druge", "strane"]
print(list2[1])

Грешке атрибута

У Питону, AttributeError се јавља када покушате да користите атрибут који не постоји на објекту или позовете метод који не постоји на објекту над којим се позива. AttributeError указује да објекат нема атрибут или метод који се на њега позива.

На пример, ако позовете метод ниске на целом броју, појавиће се AttributeError, јер метод не постоји на типу објекта над којим га позивате.

У примеру испод, метод capitalize(), који се користи за претварање првог слова ниске у велико, позива се на целом броју. Резултат је грешка атрибута јер int нема метод capitalize().

# AttributeError zbog pozivanja capitalize() na celoj brojnoj vrednosti
num = 1445
cap = num.capitalize()
print(cap)

Покретање овог кода доводи до поруке о грешци приказане у наставку:

Порука AttributeError из кода је следећа:

  File "/home/madici/Desktop/helloworld.py", line 3, in 
    cap = num.capitalize()
          ^^^^^^^^^^^^^^
AttributeError: 'int' object has no attribute 'capitalize'

Да бисте решили AttributeError, уверите се да метод или атрибут који позивате постоји на типу објекта над којим га позивате. У овом случају, позивање capitalize() на стринг типу података решава ову грешку, као што је приказано у наставку:

Грешке увоза

ImportError у Питону се појављује када покушате да увезете модул који не може да се пронађе или није доступан у вашем тренутном окружењу. Можда још није инсталиран, нисте правилно конфигурисали његову путању, или сте погрешно написали име модула који покушавате да инсталирате.

ImportError има једну подкласу која се зове ModuleNotFoundError, што је грешка која се јавља када покушате да увезете модул који не може да се пронађе.

На пример, код у наставку, у којем се покушава увоз библиотеке за анализу података pandas, даје такву грешку јер модул још није инсталиран.

Генерисана порука ImportError је приказана у наставку:

  File "/home/madici/Desktop/helloworld.py", line 1, in 
    import pandas
ModuleNotFoundError: No module named 'pandas'

Да бисте решили овакву грешку, уверите се да су модули које покушавате да увезете инсталирани. Ако ово не реши грешку, проверите да ли користите исправно писање имена модула и исправну путању до датотеке за приступ модулу.

Грешке вредности

Ово је изузетак који се јавља када функција у Питону прими вредност исправног типа података, али је та вредност неприкладна. На пример, функција math.sqrt(), која се користи за проналажење квадратног корена нумеричких вредности, вратиће ValueError ако проследите негативан број.

Без обзира на то што је вредност исправног типа, односно нумеричка, негативна вредност је чини неприкладном.

Функција int(), која конвертује број или ниску, вратиће ValueError ако проследите ниску која није нумеричка вредност ниске. Прослеђивање низова „123“ или „45“ функцији не враћа грешку, јер се ниске могу претворити у одговарајућу целобројну вредност.

Међутим, ако проследите ниску која није нумеричка вредност ниске, попут „Здраво“, враћа се ValueError. То је зато што „Здраво“, иако је ниска, није прикладно, јер нема еквивалент у целом броју.

Пример кода који генерише ValueError је приказан у наставку:

# ValueError zbog neprikladne celobrojne vrednosti u sqrt()
import math
num = -64
root = math.sqrt(num)
print(root)

# ValueError zbog prosleđivanja niske bez celobrojnog
# ekvivalenta funkciji int()
numString = "Здраво"
num = int(numString)
print(num)

Грешке из горњег кода су приказане у наставку:

Генерисана порука о грешци је следећа:

  File "/home/madici/Desktop/helloworld.py", line 4, in 
    root = math.sqrt(num)
           ^^^^^^^^^^^^^^
ValueError: math domain error

Да бисте исправили грешку, користите одговарајуће вредности у функцијама, као што је приказано у наставку:

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

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

Грешке улаза/излаза

IOError (Input/Output Error) је изузетак који се јавља када операција улаза или излаза не успе. То може бити узроковано покушајем приступа датотеци која не постоји, недовољним простором за складиштење на уређају, покушајем приступа датотеци за коју немате довољно дозвола за приступ, или када покушате да приступите датотеци која је тренутно у употреби другим операцијама.

Методе попут open(), read(), write() и close(), које се обично користе приликом рада са датотекама, су оне које ће вероватно изазвати ову грешку.

Размотрите код испод који покушава да отвори датотеку под називом „notes.txt“, која не постоји. Код резултира IOError-om, који подиже FileNotFoundError:

Са следећом поруком о грешци:

  File "/home/madici/Desktop/helloworld.py", line 2, in 
    file1 = open("notes.txt", "r")
            ^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'notes.txt'

Да бисте избегли горњу грешку, потребно је само да обезбедите да датотека „notes.txt“ постоји у директоријуму из којег покрећете терминал. Други начин за решавање IOErrors-а је коришћење try-except блока, као што је приказано у наставку:

Грешке имена

NameError је изузетак на који ћете наићи када покушате да користите променљиву, функцију или модул који не постоји, није дефинисан у тренутном опсегу, или му није додељена вредност.

Ова грешка се обично јавља када погрешно напишете имена променљивих или функција, или их користите пре него што су дефинисане. Коришћење модула без претходног увоза такође ће довести до грешке имена.

Следећи код ће резултирати изузетком NameError:

# name error se javlja zato sto math modul nije uvezen
num = 64
root = math.sqrt(64)
print(root)

# NameError se javlja zato sto se x koristi pre nego sto je definisan
y = 23
print(x)

#NameError zato sto ime funkcije nije definisano
def pozdrav():
    print("Dobro jutro")
pozdrav() #NameError: name 'pozdrav' is not defined

Следеће поруке о грешци су резултат горњег кода:

Пример поруке NameError је приказан испод:

  File "/home/madici/Desktop/helloworld.py", line 3, in 
    root = math.sqrt(64)
           ^^^^
NameError: name 'math' is not defined

Да бисте решили овакав NameError, уверите се да не користите модуле пре него што их увезете, да не користите променљиве или функције пре него што их дефинишете, и да нисте погрешно написали имена функција или променљивих:

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

y = 23
print(y)

def pozdrav():
    print("Dobro jutro")
pozdrav()

Грешке индекса

IndexError је изузетак који се јавља када покушате да приступите индексу у листи или торки који је ван опсега. Размотрите листу у наставку:

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

Листа има пет елемената. Питон броји индексе од 0 (нуле). Према томе, горња листа има индексе у опсегу од 0 до n-1, где је n број елемената у листи. У овом случају, индекс или листа ће се кретати од 0 до 4.

Ако покушате да приступите елементу са индексом већим од 4, доћи ће до IndexError-а, јер је индекс ван опсега у листи из које покушавате да приступите елементу. Следећи код генерише IndexError:

list1 = [1, 2, 3, 4, 5]
item = list1[6] #IndexError jer je indeks liste van opsega
print(item)

Грешка из горњег кода је приказана у наставку:

Генерисана порука IndexError је следећа:

  File "/home/madici/Desktop/helloworld.py", line 2, in 
    item = list1[6] #IndexError jer je indeks liste van opsega
           ~~~~~^^^
IndexError: list index out of range

Најбољи начин да избегнете IndexError је да користите функције range() и len() како бисте били сигурни да приступате само елементима који су у опсегу, на следећи начин:

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

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

Грешке кључа

KeyError је изузетак који се јавља када покушате да приступите елементу у речнику користећи кључ који не постоји у речнику. Размотрите речник у наставку:

cities = {"Canada": "Otava", "USA": "Vašington", "Italy": "Rim"}

Кључеви у речнику су „Canada“, „USA“, „Italy“. Можете приступити елементима из речника градова помоћу ових кључева. Међутим, ако покушате да приступите елементу користећи кључ који не постоји, као што је „Brazil“, појавиће се KeyError, као што је приказано у наставку:

Генерисана порука KeyError је приказана у наставку:

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

Да бисте решили KeyError, уверите се да кључеви које користите за приступ елементима у речнику заиста постоје у речнику. Да бисте то урадили, можете да наведете if…else изјаву на следећи начин:

cities = {"Canada": "Otava", "USA": "Vašington", "Italy": "Rim"}

country = "Canada"

if country in cities:
    print("Glavni grad " + country + " je " + cities[country])
else:
    print("Kljuc " + country + " ne postoji u recniku gradova")

На овај начин ћете избећи да се сусретнете са KeyError-има приликом приступа елементима из речника.

Закључак

Када кодирате у Питону, без обзира на ниво ваше стручности, неминовно ћете се сусрести са грешкама. Зато се упознајте са различитим типовима грешака наведеним у чланку, како бисте били спремни да их решите када се појаве.

Такође, можете истражити корисне Питон једноредне изразе, како бисте поједноставили честе задатке.