10. Xatolarni boshqarish¶
Dastur ishlayotganda turli xil xatolar yuz berishi mumkin.
Masalan:
son = int(
input("Son kiriting: ")
)
Foydalanuvchi:
salom
kiritsa, dastur xatolik bilan to‘xtaydi.
Bunday vaziyatlarni boshqarish uchun Python'da istisnolarni boshqarish mexanizmi mavjud.
Asosiy konstruksiyalar:
try
except
else
finally
raise
Xatolik nima?¶
Xatolik dastur bajarilishi vaqtida kutilmagan holat yuz berganda paydo bo‘ladi.
Masalan:
birinchi_son = 10
ikkinchi_son = 0
natija = (
birinchi_son
/ ikkinchi_son
)
print(
natija
)
Bu kod:
ZeroDivisionError
xatoligini beradi.
Chunki sonni nolga bo‘lish mumkin emas.
SyntaxError¶
Kod sintaksisi noto‘g‘ri bo‘lsa, SyntaxError yuz beradi.
Masalan:
if True
print("Salom")
Bu kodda : yetishmaydi.
Python kodni bajarishdan oldin sintaksis xatosini aniqlaydi.
To‘g‘ri variant:
if True:
print(
"Salom, Softromeda!"
)
NameError¶
Mavjud bo‘lmagan o‘zgaruvchidan foydalanilganda NameError yuz beradi.
print(
foydalanuvchi_nomi
)
Agar foydalanuvchi_nomi oldindan yaratilmagan bo‘lsa:
NameError
yuz beradi.
TypeError¶
Noto‘g‘ri turdagi qiymatlar bilan amal bajarilganda TypeError yuz berishi mumkin.
birinchi_son = 10
ikkinchi_son = "20"
natija = (
birinchi_son
+ ikkinchi_son
)
Bu yerda int va str qiymatlarni to‘g‘ridan-to‘g‘ri qo‘shib bo‘lmaydi.
ValueError¶
Qiymat turi to‘g‘ri bo‘lsa ham, qiymatning o‘zi yaroqsiz bo‘lsa ValueError yuz beradi.
yosh = int(
"yigirma"
)
"yigirma" matnini intga aylantirib bo‘lmaydi.
IndexError¶
Listdagi mavjud bo‘lmagan indeksga murojaat qilinsa:
mevalar = [
"olma",
"banan"
]
print(
mevalar[5]
)
IndexError yuz beradi.
KeyError¶
Dictionaryda mavjud bo‘lmagan kalitga murojaat qilinsa:
foydalanuvchi = {
"ism": "Softromeda"
}
print(
foydalanuvchi["yosh"]
)
KeyError yuz beradi.
AttributeError¶
Obyektda mavjud bo‘lmagan atribut yoki metodga murojaat qilinsa:
matn = "Softromeda"
matn.mavjud_emas()
AttributeError yuz beradi.
try¶
Xatolik yuz berishi mumkin bo‘lgan kod try ichiga yoziladi.
try:
son = int(
input("Son kiriting: ")
)
print(
f"Siz {son} sonini kiritdingiz."
)
except:
print(
"Xatolik yuz berdi."
)
Agar foydalanuvchi:
25
kiritsa:
Siz 25 sonini kiritdingiz.
Agar:
salom
kiritsa:
Xatolik yuz berdi.
Muayyan xatoni ushlash¶
Bo‘sh except ishlatishdan ko‘ra, qaysi xatoni boshqarayotganimizni ko‘rsatish yaxshiroq.
try:
son = int(
input("Son kiriting: ")
)
except ValueError:
print(
"Iltimos, faqat son kiriting."
)
Bu yerda faqat ValueError boshqariladi.
Bir nechta except¶
Bir nechta turdagi xatolarni alohida boshqarish mumkin.
try:
birinchi_son = int(
input("Birinchi son: ")
)
ikkinchi_son = int(
input("Ikkinchi son: ")
)
natija = (
birinchi_son
/ ikkinchi_son
)
print(
f"Natija: {natija}"
)
except ValueError:
print(
"Iltimos, son kiriting."
)
except ZeroDivisionError:
print(
"Sonni nolga bo‘lish mumkin emas."
)
except ichida xatoni olish¶
Xatolik obyektini o‘zgaruvchiga saqlash mumkin.
try:
son = int(
"salom"
)
except ValueError as xatolik:
print(
f"Xatolik: {xatolik}"
)
else¶
try muvaffaqiyatli ishlasa, else bajariladi.
try:
son = int(
input("Son kiriting: ")
)
except ValueError:
print(
"Noto‘g‘ri son."
)
else:
print(
f"Siz {son} sonini kiritdingiz."
)
Tuzilishi:
try
↓
Xatolik bormi?
↓
Ha → except
↓
Yo‘q → else
finally¶
finally ichidagi kod xatolik bo‘lishidan qat’i nazar bajariladi.
try:
son = int(
input("Son kiriting: ")
)
except ValueError:
print(
"Noto‘g‘ri qiymat."
)
finally:
print(
"Dastur yakunlandi."
)
try-except-else-finally¶
Barcha qismlarni birga ishlatish mumkin:
try:
birinchi_son = int(
input("Birinchi son: ")
)
ikkinchi_son = int(
input("Ikkinchi son: ")
)
natija = (
birinchi_son
/ ikkinchi_son
)
except ValueError:
print(
"Sonlarni to‘g‘ri kiriting."
)
except ZeroDivisionError:
print(
"Ikkinchi son nol bo‘lishi mumkin emas."
)
else:
print(
f"Natija: {natija}"
)
finally:
print(
"Hisoblash yakunlandi."
)
raise¶
Dasturchi o‘zi xatolik chiqarishi uchun raise ishlatiladi.
yosh = -5
if yosh < 0:
raise ValueError(
"Yosh manfiy bo‘lishi mumkin emas."
)
Funksiyada raise¶
def yoshni_tekshir(
yosh
):
if yosh < 0:
raise ValueError(
"Yosh manfiy bo‘lishi mumkin emas."
)
return yosh
Foydalanish:
try:
yosh = yoshni_tekshir(
-5
)
except ValueError as xatolik:
print(
f"Xatolik: {xatolik}"
)
Foydalanuvchi ma’lumotini tekshirish¶
raise foydalanuvchi ma’lumotlarini tekshirishda juda foydali.
def yoshni_tekshir(
yosh
):
if yosh < 0:
raise ValueError(
"Yosh 0 dan kichik bo‘lishi mumkin emas."
)
if yosh > 150:
raise ValueError(
"Yosh juda katta."
)
return yosh
Keyin:
try:
yosh = int(
input("Yoshingizni kiriting: ")
)
yoshni_tekshir(
yosh
)
print(
"Yosh qabul qilindi."
)
except ValueError as xatolik:
print(
f"Xatolik: {xatolik}"
)
assert¶
assert dasturdagi shartni tekshirish uchun ishlatiladi.
yosh = 25
assert yosh >= 0
Agar shart noto‘g‘ri bo‘lsa:
AssertionError
yuz beradi.
Xabar bilan:
yosh = -5
assert yosh >= 0, (
"Yosh manfiy bo‘lishi mumkin emas."
)
assert va raise farqi¶
assert ko‘proq dasturchining ichki taxminlarini tekshirish uchun ishlatiladi.
assert foydalanuvchi is not None
raise esa dastur logikasida kutilgan noto‘g‘ri holatni aniq boshqarish uchun ishlatiladi.
if yosh < 0:
raise ValueError(
"Yosh noto‘g‘ri."
)
O‘zimizning exception classimiz¶
Python'da o‘zimizga kerakli xatolik turini yaratishimiz mumkin.
class YoshXatoligi(Exception):
pass
Keyin:
def yoshni_tekshir(
yosh
):
if yosh < 0:
raise YoshXatoligi(
"Yosh manfiy bo‘lishi mumkin emas."
)
Foydalanish:
try:
yoshni_tekshir(
-5
)
except YoshXatoligi as xatolik:
print(
f"Xatolik: {xatolik}"
)
Exception meros olish¶
Maxsus xatoliklar odatda Exceptiondan meros oladi.
class MalumotXatoligi(
Exception
):
pass
Keyin:
class YoshXatoligi(
MalumotXatoligi
):
pass
Bu katta dasturlarda xatoliklarni guruhlash uchun foydali.
Xatoliklarni qayta ko‘tarish¶
Ba’zan xatoni ushlab, keyin yana yuqoriga yuborish kerak bo‘ladi.
try:
son = int(
"salom"
)
except ValueError:
print(
"Qiymatni aylantirishda xatolik."
)
raise
raise argumentlarsiz yozilsa, ushlangan xatolikni qayta chiqaradi.
Xatoliklar iyerarxiyasi¶
Python'dagi ko‘plab xatoliklar umumiy Exception sinfidan kelib chiqadi.
Masalan:
Exception
│
├── ValueError
├── TypeError
├── IndexError
├── KeyError
├── NameError
└── ZeroDivisionError
Shuning uchun quyidagisi ko‘plab xatoliklarni ushlashi mumkin:
try:
natija = int(
"salom"
)
except Exception as xatolik:
print(
f"Xatolik: {xatolik}"
)
Lekin imkon qadar aniq exception turini ushlash yaxshi amaliyot hisoblanadi.
Bir nechta xatolikni bitta exceptda boshqarish¶
try:
son = int(
input("Son kiriting: ")
)
except (
ValueError,
TypeError
):
print(
"Qiymat noto‘g‘ri."
)
Xatolik bilan birga else¶
try:
son = int(
input("Son kiriting: ")
)
except ValueError:
print(
"Son noto‘g‘ri."
)
else:
kvadrat = (
son ** 2
)
print(
f"Kvadrat: {kvadrat}"
)
Bu yerda hisoblash faqat son muvaffaqiyatli o‘qilganida amalga oshadi.
finally qachon foydali?¶
finally resurslarni tozalashda ayniqsa foydali.
Masalan:
fayl = None
try:
fayl = open(
"malumot.txt",
"r"
)
matn = fayl.read()
print(
matn
)
except OSError:
print(
"Faylni ochishda xatolik."
)
finally:
if fayl is not None:
fayl.close()
print(
"Fayl yopildi."
)
Keyinchalik fayllar bilan ishlashda with konstruksiyasi bundan ham qulayroq usul ekanini ko‘ramiz.
Noto‘g‘ri usul¶
Quyidagicha juda umumiy exception ushlash muammolarni yashirishi mumkin:
try:
juda_muhim_amallar()
except:
pass
Bu yomon amaliyot.
Chunki dasturda xatolik yuz beradi, lekin hech qanday ma’lumot ko‘rsatilmaydi.
Natijada muammoni topish qiyinlashadi.
Yaxshiroq:
try:
juda_muhim_amallar()
except ValueError as xatolik:
print(
f"Qiymat xatoligi: {xatolik}"
)
Xatolikni foydalanuvchiga tushunarli qilish¶
Texnik xatolikni to‘g‘ridan-to‘g‘ri foydalanuvchiga ko‘rsatish har doim ham yaxshi emas.
Masalan:
try:
yosh = int(
input("Yoshingizni kiriting: ")
)
except ValueError:
print(
"Iltimos, yoshingizni raqam bilan kiriting."
)
Bu foydalanuvchi uchun ancha tushunarli.
Qayta urinish¶
Xatolik yuz berganda foydalanuvchidan yana qiymat olish mumkin.
while True:
try:
yosh = int(
input("Yoshingizni kiriting: ")
)
break
except ValueError:
print(
"Iltimos, faqat son kiriting."
)
print(
f"Sizning yoshingiz: {yosh}"
)
Agar foydalanuvchi noto‘g‘ri qiymat kiritsa, dastur yana so‘raydi.
Cheklangan urinishlar¶
Foydalanuvchiga uchta imkoniyat berish:
urinishlar_soni = 3
while urinishlar_soni > 0:
try:
yosh = int(
input("Yoshingizni kiriting: ")
)
if yosh < 0:
raise ValueError(
"Yosh manfiy bo‘lishi mumkin emas."
)
print(
f"Qabul qilindi: {yosh}"
)
break
except ValueError as xatolik:
urinishlar_soni -= 1
print(
f"Xatolik: {xatolik}"
)
print(
f"Qolgan urinishlar: {urinishlar_soni}"
)
Funksiya va exception¶
Funksiya ichida exception yuz berishi mumkin.
def bolish(
birinchi_son,
ikkinchi_son
):
if ikkinchi_son == 0:
raise ZeroDivisionError(
"Nolga bo‘lish mumkin emas."
)
return (
birinchi_son
/ ikkinchi_son
)
Keyin:
try:
natija = bolish(
10,
0
)
except ZeroDivisionError as xatolik:
print(
f"Xatolik: {xatolik}"
)
Exception va return¶
Xatolikni qaytarish uchun returndan foydalanish mumkin, lekin bu har doim ham yaxshi yechim emas.
Masalan:
def bolish(
birinchi_son,
ikkinchi_son
):
if ikkinchi_son == 0:
return None
return (
birinchi_son
/ ikkinchi_son
)
Bu oddiy vaziyatlarda ishlashi mumkin.
Lekin murakkab dasturlarda xatolikni raise qilish ko‘pincha aniqroq:
def bolish(
birinchi_son,
ikkinchi_son
):
if ikkinchi_son == 0:
raise ValueError(
"Ikkinchi son nol bo‘lishi mumkin emas."
)
return (
birinchi_son
/ ikkinchi_son
)
Amaliy mashqlar¶
Mashq 1¶
Foydalanuvchidan ikkita son qabul qiling va ularni bo‘ling.
Quyidagi xatoliklarni boshqaring:
ValueError
ZeroDivisionError
Mashq 2¶
Foydalanuvchidan indeks qabul qilib, list elementini chiqaring.
IndexErrorni boshqaring.
Mashq 3¶
Dictionarydan foydalanuvchi kiritgan kalit bo‘yicha qiymat oling.
KeyErrorni boshqaring.
Mashq 4¶
Manfiy yosh uchun ValueError ko‘taring.
Mashq 5¶
YoshXatoligi nomli maxsus exception yarating.
Mashq 6¶
Foydalanuvchiga faqat uch marta noto‘g‘ri qiymat kiritish imkonini bering.
Mashq 7¶
try, except, else va finallyning barchasidan foydalanadigan dastur yozing.
Mashq 8¶
Bir nechta exceptionni bitta except orqali boshqaring.
Mini loyiha — Softromeda kalkulyator¶
Foydalanuvchidan ikkita son va amal qabul qilamiz.
def hisobla(
birinchi_son,
ikkinchi_son,
amal
):
if amal == "+":
return (
birinchi_son
+ ikkinchi_son
)
if amal == "-":
return (
birinchi_son
- ikkinchi_son
)
if amal == "*":
return (
birinchi_son
* ikkinchi_son
)
if amal == "/":
if ikkinchi_son == 0:
raise ZeroDivisionError(
"Nolga bo‘lish mumkin emas."
)
return (
birinchi_son
/ ikkinchi_son
)
raise ValueError(
"Noma’lum amal."
)
try:
birinchi_son = float(
input("Birinchi sonni kiriting: ")
)
ikkinchi_son = float(
input("Ikkinchi sonni kiriting: ")
)
amal = input(
"Amalni kiriting (+, -, *, /): "
)
natija = hisobla(
birinchi_son,
ikkinchi_son,
amal
)
except ValueError as xatolik:
print(
f"Qiymat xatoligi: {xatolik}"
)
except ZeroDivisionError as xatolik:
print(
f"Hisoblash xatoligi: {xatolik}"
)
else:
print(
f"Natija: {natija}"
)
finally:
print(
"Softromeda kalkulyatori yakunlandi."
)
Masalan:
Birinchi sonni kiriting: 20
Ikkinchi sonni kiriting: 5
Amalni kiriting (+, -, *, /): /
Natija: 4.0
Softromeda kalkulyatori yakunlandi.
Agar ikkinchi son 0 bo‘lsa:
Hisoblash xatoligi: Nolga bo‘lish mumkin emas.
Softromeda kalkulyatori yakunlandi.
Bob xulosasi¶
Bu bobda Python'da xatolarni boshqarishni o‘rgandik.
Asosiy tushunchalar:
SyntaxError
NameError
TypeError
ValueError
IndexError
KeyError
AttributeError
ZeroDivisionError
Xatolarni boshqarish:
try
except
else
finally
Xatolik yaratish:
raise
Shartni tekshirish:
assert
Maxsus xatolik yaratish:
class YoshXatoligi(Exception):
pass
Eng muhim tamoyil:
Xatolik yuz berishi mumkin
↓
try
↓
Xatolik yuz berdimi?
↓ ↓
ha yo‘q
↓ ↓
except else
↓ ↓
finally
Keyingi bobda Python'da fayllar bilan ishlash, fayl o‘qish va yozish, with, CSV va JSON formatlarini o‘rganamiz.