Xatolar va ularni tuzatish

Har bir dasturchi — hatto eng tajribalisi ham — har kuni xato qiladi. Professionalni yangi boshlovchidan ajratib turadigan narsa xatosizlik emas, balki xatoni tez topib, tuzata olish. Bu darsda aynan shu mahoratni o'rganamiz.

Bu darsda

  • Xatolarning uch turi
  • Xato xabarini (traceback) o'qish
  • Eng ko'p uchraydigan xatolar va ularning sabablari
  • try / except — xatolarni ushlash
  • Xatolarni topishning amaliy usullari

Inglizcha «bug» (qo'ng'iz, hasharot) so'zi dasturdagi xatoni bildiradi, xatoni tuzatish esa debugging deyiladi. Mashhur rivoyatga ko'ra, 1947-yilda Garvard universitetidagi Mark II kompyuteri ishdan chiqqanda, uning ichidan haqiqiy kapalak topilgan. Muhandislar uni jurnalga yopishtirib, «Haqiqiy bug topilgan birinchi holat» deb yozib qo'yishgan. O'sha sahifa hozir ham muzeyda saqlanadi.

Xatolarning uch turi

1. Sintaksis xatolari

Kod Python qoidalariga mos emas — qavs yopilmagan, ikki nuqta tushib qolgan, qo'shtirnoq yetishmaydi. Python bunday kodni umuman ishga tushirmaydi, darhol SyntaxError beradi. Bu eng oson tuzatiladigan xatolar: Python joyini aniq ko'rsatadi.

print("Dastur boshlandi")
if 5 > 3
    print("Besh uchdan katta")

E'tibor bering: birinchi qator ham bajarilmadi. Sintaksis xatosi bo'lsa, Python kodni boshlamasdanoq to'xtaydi.

2. Bajarilish paytidagi xatolar

Kod to'g'ri yozilgan, lekin bajarilayotganda imkonsiz ish uchradi: nolga bo'lish, yo'q faylni ochish, matnni songa aylantirish. Bunday xatolar istisno (inglizcha exception) deyiladi. Dastur xatoga yetguncha ishlaydi, keyin to'xtaydi:

print("Hisob boshlandi")
pul = 100000
odamlar = 0
print("Har biriga:", pul / odamlar)
print("Bu qator bajarilmaydi")

3. Mantiqiy xatolar

Eng ayyor xatolar. Dastur xatosiz ishlaydi, lekin noto'g'ri natija beradi. Python hech narsa demaydi — chunki u siz nima qilmoqchi ekaningizni bilmaydi:

a = 4
b = 5
c = 3
ortacha = a + b + c / 3
print("O'rtacha:", ortacha)

Natija 10.0 chiqdi, lekin 4, 5, 3 ning o'rtachasi 4 bo'lishi kerak! Sabab — amallar tartibi: faqat c 3 ga bo'lindi. To'g'risi: (a + b + c) / 3. Mantiqiy xatolarni topishning yagona yo'li — natijani diqqat bilan tekshirish.

Xato xabarini o'qish

Python xato haqida xabar berganda, u traceback («izni kuzatish») deb ataladigan hisobot chiqaradi. Uni qo'rqmasdan o'qishni o'rganing — u xatoni topishdagi eng yaxshi yordamchingiz:

def ortacha(sonlar):
    return sum(sonlar) / len(sonlar)

baholar = []
print(ortacha(baholar))
Traceback (most recent call last):
  File "<kod>", line 5, in <module>
    print(ortacha(baholar))
          ~~~~~~~^^^^^^^^^
  File "<kod>", line 2, in ortacha
    return sum(sonlar) / len(sonlar)
           ~~~~~~~~~~~~^~~~~~~~~~~~~
ZeroDivisionError: division by zero

Traceback'ni pastdan yuqoriga o'qing:

  1. Oxirgi qator — eng muhimi: xato turi (ZeroDivisionError) va sababi (division by zero — «nolga bo'lish»).
  2. Undan yuqorisi — xato aynan qayerda bo'lgani: 2-qator, ortacha funksiyasi ichida. ^ belgilari muammoli qismni ko'rsatadi.
  3. Eng yuqorisi — bu funksiya qayerdan chaqirilgani: 5-qator.

Xulosa: bo'sh ro'yxat uzunligi 0, unga bo'lish mumkin emas. Yechim — ro'yxat bo'sh emasligini oldindan tekshirish.

Eng ko'p uchraydigan xatolar

XatoMa'nosiOdatiy sababi
SyntaxErrorYozish qoidasi buzilganQavs, qo'shtirnoq yoki : yetishmaydi
IndentationErrorChekinish noto'g'riBlokda bo'sh joylar soni har xil
NameErrorBunday nom yo'qO'zgaruvchi nomi xato yozilgan yoki unga hali qiymat berilmagan
TypeErrorTur mos emas"5" + 3 — matn va sonni qo'shish
ValueErrorQiymat yaroqsizint("salom")
ZeroDivisionErrorNolga bo'lishBo'luvchi 0 ga teng
IndexErrorBunday indeks yo'q3 elementli ro'yxatda [3] so'raldi
KeyErrorBunday kalit yo'qLug'atda kalit mavjud emas
AttributeErrorBunday metod yo'q"salom".push() — satrda push metodi yo'q

Bu saytdagi muharrir har bir xato ostida uning o'zbekcha tushuntirishini beradi va xato qatorini qizil rang bilan belgilaydi. Lekin asl xabarni ham o'qishga odatlaning — kompyuteringizdagi Python faqat inglizcha xabar beradi.

try / except — xatolarni ushlash

Ba'zi xatolarni oldindan bilish mumkin. Masalan, foydalanuvchi son o'rniga harf yozishi mumkin. Bunday holatda dastur «yiqilib» qolmasligi uchun xatoni ushlab, o'zimiz hal qilamiz:

try:
    yosh = int(input("Yoshingiz: "))
    print("Kelasi yili", yosh + 1, "yoshda bo'lasiz")
except ValueError:
    print("Iltimos, yoshingizni raqam bilan yozing.")
Yoshingiz: o'n yetti
Iltimos, yoshingizni raqam bilan yozing.

Qanday ishlaydi:

  1. Python try («urinib ko'r») blokini bajaradi.
  2. Agar u yerda xato bo'lmasa — except bloki tashlab o'tiladi.
  3. Agar ValueError yuz bersa — try blokining qolgan qismi bajarilmaydi, darhol except («istisno holda») blokiga o'tiladi. Dastur to'xtamaydi!

To'g'ri javob berilguncha so'rash

while True, try va break birgalikda foydalanuvchi to'g'ri son kiritguncha so'rab turadi. Bu juda ko'p ishlatiladigan andoza:

while True:
    try:
        son = int(input("Butun son kiriting: "))
        break                      # xato bo'lmasa, sikldan chiqamiz
    except ValueError:
        print("Bu butun son emas. Qaytadan urinib ko'ring.")

print("Rahmat! Siz", son, "kiritdingiz.")
Butun son kiriting: abc
Bu butun son emas. Qaytadan urinib ko'ring.
Butun son kiriting: 12.5
Bu butun son emas. Qaytadan urinib ko'ring.
Butun son kiriting: 7
Rahmat! Siz 7 kiritdingiz.

Bir nechta xato turi

Turli xatolar uchun turli except bloklarini yozish mumkin:

try:
    a = int(input("Bo'linuvchi: "))
    b = int(input("Bo'luvchi: "))
    print("Natija:", a / b)
except ValueError:
    print("Faqat butun son kiriting.")
except ZeroDivisionError:
    print("Nolga bo'lib bo'lmaydi.")

Shunchaki except: deb, xato turini ko'rsatmasdan yozish mumkin, lekin bu yomon odat. Bunday blok barcha xatolarni, jumladan siz kutmagan va bilishingiz kerak bo'lgan xatolarni ham «yutib yuboradi». Har doim aniq xato turini yozing.

Xato xabarini olish

as yordamida xato haqidagi ma'lumotni o'zgaruvchiga olish mumkin:

mahsulotlar = {"non": 4000, "sut": 12000}
try:
    print(mahsulotlar["qatiq"])
except KeyError as xato:
    print("Topilmadi:", xato)

Xatolarni topish usullari

Xato xabari bo'lmasa (mantiqiy xato) yoki u tushunarsiz bo'lsa, quyidagi usullar yordam beradi:

  1. Xabarni oxirigacha o'qing. Ko'pincha javob o'sha yerda yozilgan bo'ladi. Python hatto Did you mean...? («...demoqchimidingiz?») deb maslahat ham beradi.
  2. print() bilan kuzating. Shubhali joylarga o'zgaruvchilar qiymatini chiqaradigan qatorlar qo'ying: print("DEBUG: x =", x, type(x)). Qiymat kutganingizdek emasligini ko'rgan joyingiz — xato atrofi.
  3. Kichik qismlarga bo'ling. Dasturning yarmini izohga aylantirib, xato qaysi qismda ekanini aniqlang.
  4. Qo'lda kuzating. 10-darsdagi kabi jadval chizib, har bir qadamda o'zgaruvchilar qiymatini qog'ozda yozing.
  5. «O'yinchoq o'rdak» usuli. Kodingizni qatorma-qator kimgadir — hatto stol ustidagi o'yinchoqqa — ovoz chiqarib tushuntiring. Ko'pincha tushuntirish jarayonida xato o'zi ko'zga tashlanadi. Bu usul dasturchilar orasida jiddiy ravishda rubber duck debugging deb ataladi.
  6. Internetdan qidiring. Xato xabarining oxirgi qatorini nusxalab, qidiruv tizimiga yozing. Siz bu xatoga duch kelgan birinchi odam emassiz — javob deyarli doim bor.
  7. Dam oling. Bir soat xato qidirib topa olmasangiz, 10 daqiqa tanaffus qiling. Toza ko'z bilan qaraganda xato ko'pincha darhol ko'rinadi.

Mashqlar

1-mashq Uchta xato

Dasturda uchta xato bor: sintaksis, nom va mantiqiy. Hammasini tuzating — dastur Jami: 15000 va O'rtacha: 5000.0 chiqarishi kerak.

narxlar = [4000, 5000, 6000]
jami = 0
for narx in narxlar
    jami += narx
print("Jami:", Jami)
print("O'rtacha:", jami / len(narxlar) + 1)
Ishora

Python xatolarni birma-bir ko'rsatadi. Sintaksis xatosini tuzatgach, keyingisi chiqadi. Mantiqiy xatoni esa natijani kutilgani bilan solishtirib topasiz.

Yechimni ko'rish
narxlar = [4000, 5000, 6000]
jami = 0
for narx in narxlar:
    jami += narx
print("Jami:", jami)
print("O'rtacha:", jami / len(narxlar))

3-qatorda : yetishmagan (sintaksis), 5-qatorda Jami katta harf bilan yozilgan (nom), 6-qatorda esa ortiqcha + 1 bor edi (mantiqiy).

2-mashq Xavfsiz bo'lish

bolish(a, b) funksiyasini yozing: u a / b ni qaytarsin, lekin b nol bo'lsa, xato o'rniga Nolga bo'lib bo'lmaydi matnini qaytarsin. try / except dan foydalaning.

def bolish(a, b):
    return a / b

print(bolish(10, 2))
print(bolish(1, 0))
Yechimni ko'rish
def bolish(a, b):
    try:
        return a / b
    except ZeroDivisionError:
        return "Nolga bo'lib bo'lmaydi"

print(bolish(10, 2))
print(bolish(1, 0))

3-mashq Musbat son

Foydalanuvchidan musbat butun son so'rang. U harf yozsa — Bu son emas, manfiy son yoki nol yozsa — Son musbat bo'lishi kerak deb, qaytadan so'rang. To'g'ri son kiritilgach, uning kvadratini chiqaring.

# Kodingizni shu yerga yozing
Yechimni ko'rish
while True:
    try:
        son = int(input("Musbat son: "))
    except ValueError:
        print("Bu son emas")
        continue
    if son <= 0:
        print("Son musbat bo'lishi kerak")
        continue
    break

print("Kvadrati:", son ** 2)
Musbat son: besh
Bu son emas
Musbat son: -5
Son musbat bo'lishi kerak
Musbat son: 5
Kvadrati: 25

O'zingizni sinang

Qaysi xato turida Python hech qanday xabar bermaydi?

  1. Sintaksis xatosi
  2. Bajarilish paytidagi xato
  3. Mantiqiy xato
  4. Python har doim xabar beradi

To'g'ri. Mantiqiy xatoda dastur ishlaydi, lekin noto'g'ri natija beradi.

Traceback'ning qaysi qismini birinchi navbatda o'qish kerak?

  1. Oxirgi qatorni — xato turi va sababini
  2. Birinchi qatorni — «Traceback»
  3. O'rtadagi ^ belgilarini
  4. Hech birini — darhol kodni o'zgartirish kerak

To'g'ri. Pastdan yuqoriga o'qing: avval nima bo'ldi, keyin qayerda.

int("12a") qaysi xatoni beradi?

  1. TypeError
  2. NameError
  3. SyntaxError
  4. ValueError

To'g'ri. Tur to'g'ri (satr), lekin uning qiymatini butun songa aylantirib bo'lmaydi.

try blokida xato yuz bermasa, nima bo'ladi?

  1. except bloki ham bajariladi
  2. except bloki tashlab o'tiladi
  3. Dastur to'xtaydi
  4. try bloki ikki marta bajariladi

To'g'ri. except faqat xato yuz berganda ishlaydi.

Xulosa

  • Xatolar uch xil: sintaksis (kod ishga tushmaydi), bajarilish paytidagi (dastur to'xtaydi) va mantiqiy (natija noto'g'ri).
  • Traceback'ni pastdan yuqoriga o'qing: oxirgi qatorda — xato turi va sababi, yuqorida — qayerda bo'lgani.
  • try / except XatoTuri: — kutilgan xatolarni ushlab, dasturni to'xtatmasdan hal qiladi.
  • Bo'sh except: dan qoching — aniq xato turini yozing.
  • Xatoni topish uchun: xabarni o'qing, print() bilan kuzating, qismlarga bo'ling, tushuntirib ko'ring, qidiring.