#35 XATOLAR BILAN ISHLASH
Xatolarni jilovlashni o'rganamiz.
Avvalgi darslarimizning birida biz "Run time error" xatoliklari bilan tanishgan edik. Bunday xatolar dastur bajarish jarayonida kelib chiqadi va dasturning ishlashini to'xtatadi. Sintaks xatolikdan farqli ravishda Python bunday xatolarni dasturni bajarishdan avval aniqlay olmaydi.
Ushbu darsimizda qanday qilib mana shunday xatoliklarni jilovlashni o'rganamiz. Maqsadimiz xatolik yuz berganda dastur to'xtab qolishining oldini olish. Gap shundaki, dastur davomida xato yuz berganda Python maxsus exception (istisno) obyektini yaratadi. Agar bu obyekt "tutib" olinmasa, dastur bajarilishdan to'xtaydi.
Istisno obyektlarni tutib olish uchun Pythonda maxsus
try-except
operatorlari bor. Bu operatorlar quyidagicha ishlaydi, try
operatori badanida bajarish kerak bo'lgan kod yoziladi, except
operatori badanida esa xatolik yuz berganda bajarilishi kerak bo'lgan kod yoziladi. Ya'ni dasturimiz to'xtab qolmasdan bajarilaveradi. Tushunarli bo'lishi uchun quyidagi misolni ko'ramiz.
yosh = input("Yoshingizni kiriting: ")
yosh = int(yosh)
print(f"Siz {2021-yosh} yilda tug'ilgansiz")
Yuqoridagi misolning 1-qatorida biz foydalanuvchidan yoshini kiritishni so'rayabmiz. Navbatdagi qatorda esa foydalanuvchi kiritgan qiymatni int() yordamida butun songa o'tkazayapmiz. Agar foydalanuvchi yoshini kiritganda, butun emas, o'nlik son kiritsa bu
ValueError
xatoligiga olib keladi, va dastur bajarilishdan to'xtaydi.
Dastur natijasi
Keling, yuqoridagi kodni
try-except
yordamida yozamiz:yosh = input("Yoshingizni kiriting: ")
try:
yosh = int(yosh)
print(f"Siz {2021-yosh} yilda tug'ilgansiz")
except:
print("Butun son kiritmadingiz")
print("Dastur Tugadi!")
Bu yerda ham dastavval foydalanuvchi yoshini so'radik.
int()
finksiyasini esa try
badani ichida yozdik, agar foydalanuvchi to'gri qiymat kiritgan bo'lsa kodimiz foydalanuvchi tug'ilgan yilini hisoblab ko'rsatadi, exception (istisno) yuz berganda esa "Butun son kiritmadingiz"
xabarini konsolga chiqaradi. Lekin dastur bajarilishdan to'xtamaydi, va try-except blokidan keyingi qatorlar ham bajarilaveradi (print("Dastur Tugadi!")
). Buni quyidagi natijadan ham ko'rishimiz mumkin:
Dastur natijasi
try-except
operatorining afzalliklaridan biri, foydalanuvchiga tushunarsiz xatolar o'rniga, o'zimiz istagan, tushunarliroq matnni ko'rsatishimiz mumkin. Shuningdek, kompleks tizimlarda arzimagan xatoni deb dasturimiz to'xtab qolmaydi.Yuqoridagi kodimizda biz try moduli ichida xato qaytarishi mumkin bo'lgan ifodani ham (
tyil = int(tyil)
), xato qaytmaganda bajarilishi kerak bo'lgan ifodani ham (print(f"Siz {2021-tyil} yoshdasiz")
) birdan yozib ketayapmiz. Aslida, bunday qilishimiz to'g'ri emas. To'g'ri usuli, bu avval xatoga tekshirish va xato yuz bermaganda bajariladigan ifodani alohida,
else
blokida yozish:yosh = input("Yoshingizni kiriting: ")
try:
yosh = int(yosh)
except:
print("Butun son kiritmadingiz")
else:
print(f"Siz {2021-yosh} yilda tug'ilgansiz")
Albatta, yuqoridagi usul har doim ham qo'l kelavermaydi.
Xatolarning turlari ko'p,
except
operatori yordamida esa biz aynan qaysi xatolarni ushlamoqchi ekanimizni ham ko'rsatishimiz mumkin. Misol uchun yuqoridagi misolda int()
funksiyasi ValueError
xatosini qaytardi. Agar biz faqatgina shu turdagi xatolarni ushlamoqchi bo'lsak, kodimizni quyidagicha o'zgartiramiz:yosh = input("Yoshingizni kiriting: ")
try:
yosh = int(yosh)
except ValueError:
print("Butun son kiritmadingiz")
else:
print(f"Siz {2021-yosh} yilda tug'ilgansiz")
Ba'zi dastur davomida arifmetik amallar bajarilishi natijasida 0 ga bo'lish xatoligi (
ZeroDivisionError
) yuzaga kelishi mumkin. Aynan shu xatoni jilovlash uchun, except ZeroDivisionError
ifodasidan foydalanamiz:x,y=5,10
try:
y/(x-5)
except ZeroDivisionError:
print("0 ga bo'lib bo'lmaydi")
Natija:
0 ga bo'lib bo'lmaydi
Bu xatolik odatda ro'yxatda mavjud bo'lmagan indeksga murojat qilishda chiqib keladi.
mevalar = ['olma','anor','anjir','uzum']
try:
print(mevalar[7])
except IndexError:
print(f"Ro'yxatda {len(mevalar)} ta meva bor xolos")
Natija:
Ro'yxatda 4 ta meva bor xolos
Bu xatolik lug'atda mavjud bo'lmagan kalitga murojat qilishda kelib chiqadi:
user = {"username":"sariqdev",
"status":"admin",
"email":"[email protected]",
"phone":"99897123456"}
key="tel"
try:
print(f'Foydalanuvchi: {user[key]}')
except KeyError:
print("Bunday kalit mavjud emas")
Natija:
Bunday kalit mavjud emas
Avvalgi darsimizda fayllar bilan ishlashni o'rgangan edik. Fayllarni biz o'qish (
open(filename,'r')
) yoki yozish (open(filename,'w')
) uchun ochishimiz mumkin. Agar faylga ma'lumot yozish uchun ochishda, mavjud bo'lmagan faylga murojat qilsak, Python yangi fayl yaratadi. Lekin, faylni o'qish uchun ochishda fayl nomini xato yozsak, yoki mavjud bo'lmagan faylni ochmoqchi bo'lsak FileNotFoundError
(fayl topilmadi) xatoligi yuzaga keladi. filename = "data.txt" # bunday fayl mavjud emas
with open(filename) as f:
text = f.read()
Natija:
FileNotFoundError: [Errno 2] No such file or directory: 'data.txt'
Demak, bu xatolikni ham ushlab qolish uchun
except FileNotFoundError
ifodasidan foydalanamiz:filename = "data.txt" # bunday fayl mavjud emas
try:
with open(filename) as f:
text = f.read()
except FileNotFoundError:
print(f"Kechirasiz, {filename} fayli mavjud emas. Bosh fayl tanlang.")
Natija:
Kechirasiz, data.txt fayli mavjud emas. Bosh fayl tanlang.
try-except
ketma-ketligida bir nechta except
operatorlari ham bo'lishi mumkin. Ularning har biri ma'lum turdagi xatolik uchun javobgar bo'ladi:n = input("Butun son kiriting: ")
try:
n = int(n)
x=20/n
except ValueError: # agar foydalanuvchi butun son kiritmasa
print("Butun son kiritmadingiz")
except ZeroDivisionError: # agar foydalanuvchi 0 kiritsa
print("0 ga bo'lib bo'lmaydi")
else:
print(f"x={x}")
Yuqoridagi misollarda kodimiz xato qaytarganda, dasturimiz foydalanuvchiga qandaydur ma'lumotni ko'rsatayapti:
import json
files = ['talaba1.json','talaba2.json','talaba3.json','talaba4.json']
for filename in files:
try:
with open(filename) as f:
talaba = json.load(f)
except FileNotFoundError:
print(f"{filename} mavjud emas")
else:
print(talaba['ism'])
# fayl ustida turli amallar

Natija
Hech qanday ma'lumot ko'rsatmay, dasturni davom etish uchun
pass
operatoridan foydalanamiz. Odatda pass
operatoridan funksiyalar yoki operatorlarning badanini "to'ldirib" ketish uchun ishlatiladi. Ya'ni, agar biz except
operatorini yozsagu, uning badanida hech narsa bajarilishini istmasak, pass
operatorini ishlatamiz. import json
files = ['talaba1.json','talaba2.json','talaba3.json','talaba4.json']
for filename in files:
try:
with open(filename) as f:
talaba = json.load(f)
except FileNotFoundError:
pass
else:
print(talaba['ism'])
Yuqorida biz xatolar yuz berganda, ularni ushlash va dastur to'xtashining oldini olishni ko'rdik. Ya'ni,
try-except
ketma-ketligi xatolarning oldini olishga yordam bera olmaydi. Xatolarning oldini olish uchun if-else
va while
tsikllaridan foydalanganimiz afzal.Mavu boshidagi misolimizga qaytsak. Biz foydalanuvchi yoshini so'radik, va foydalanuvchi butun son kiritmagani sababli dasturni to'xtatdik. Aslida, while tsikli yordamida toki foydalanuvchi to'g'ri qiymat kritgunga qadar uning yoshini qayta-qayta talab qilishimiz mumkin:
while True:
yosh = input("Yoshingizni kiriting: ")
if yosh.isdigit():
yosh = int(yosh)
break
print(f"Siz {2021-yosh} yilda tug'ilgansiz")

Natija
Albatta yuqordagi usul barcha xatolar uchun ishlamaydi. Shunday xatolar bo'lishi mumkinki, biz ularni oldindan ko'ra olmasligimiz yoki, oldindan to'g'rila olmasligimiz, yoki xato foydalanuvchiga bog'liq bo'lmasligi mumkin. Shunday holatlarda,
try-except
operatorlari bizning xaloskorimiz bo'ladi.