Mundarija (21)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Eng oddiy shakl
- 2.2. Qachon kerak
- 2.3. Asos sinf tanlash
- 2.4. Atributlar va konstruktor
- 2.5. __str__ va __repr__
- 2.6. Kutubxona uchun loyihalash
- 2.7. Keng tarqalgan xatolar
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Asoslar va tuzoqlar
- Misol 2 — Kutubxona istisnolari
- Misol 3 — Loyihalash namunalari
- Misol 4 — Amaliy: to'lov tizimi
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
9.6-dars: O'z istisnolaringiz
9-QISM — XATOLAR VA ISTISNOLAR · 6-dars
1. Kirish va motivatsiya
Bu kod ishlaydi — lekin foydalanuvchi hech narsa tushunmaydi:
def tolov_qil(karta: str, summa: int):
if len(karta) != 16:
raise ValueError("noto'g'ri")
if summa <= 0:
raise ValueError("noto'g'ri")
if summa > balans:
raise ValueError("noto'g'ri") Uchtasi ham ValueError — ajratib bo'lmaydi:
try:
tolov_qil(k, s)
except ValueError:
... # ⚠️ qaysi biri? Nima qilish kerak?O'z istisnolaringiz bilan:
class TolovXatosi(Exception): ...
class KartaXatosi(TolovXatosi): ...
class MablagYetarliEmas(TolovXatosi):
def __init__(self, kerak: int, bor: int):
self.kerak, self.bor, self.yetishmayapti = kerak, bor, kerak - bor
super().__init__(f"{self.yetishmayapti:,} so'm yetishmayapti")try:
tolov_qil(k, s)
except KartaXatosi:
return {"xato": "Karta ma'lumotlari noto'g'ri"}, 400
except MablagYetarliEmas as e:
return {"xato": str(e), "yetishmayapti": e.yetishmayapti}, 402Bu darsda:
- Qachon o'z istisnongiz kerak
- Asos sinf tanlash (
Exception,ValueError, ...) - Atributlar va konstruktor
__str__,__repr__va serializatsiya- Keng tarqalgan xatolar
- Kutubxona uchun istisno loyihalash
2. Nazariya — chuqur tushuntirish
2.1. Eng oddiy shakl
class MeningXatom(Exception):
"""Nima uchun kerakligi shu yerda."""Uch qator — va u to'liq ishlaydi:
raise MeningXatom("xabar")
except MeningXatom as e: ...
str(e) # 'xabar'
e.args # ('xabar',) pass o'rniga docstring:
class MeningXatom(Exception):
pass # ⚠️ hujjat yo'q
class MeningXatom(Exception):
"""Sozlama yuklashda xato.""" # ✅2.2. Qachon kerak
Kerak:
# 1. Domen xatosi — o'rnatilgan tur mos kelmaydi
class MablagYetarliEmas(Exception): ...
# 2. Ajratish kerak
class VaqtinchalikXato(Exception): ... # qayta urin
class DoimiyXato(Exception): ... # urinma
# 3. Qo'shimcha ma'lumot
class SorovXatosi(Exception):
def __init__(self, xabar, *, kod, url): ...
# 4. Kutubxona API si
class KutubxonaXatosi(Exception): ... # ⭐ foydalanuvchi bitta tur
# 5. Ichki tafsilotni yashirish
raise MeningXatom(...) from NoneKerak emas:
# 1. O'rnatilgan tur to'liq mos
class MeningTypeError(Exception): ... # ⚠️ TypeError yetadi
# 2. Bitta joyda ishlatiladi
class FaqatShuYerda(Exception): ... # ⚠️ ValueError yetadi
# 3. Ajratilmaydi
except (XatoA, XatoB, XatoC): # ⚠️ nega ajratilgan?
# 4. Har funksiya uchun
class YuklashXatosi(Exception): ...
class TekshirishXatosi(Exception): ... # ⚠️ juda ko'p
class SaqlashXatosi(Exception): ...Mezon: foydalanuvchi bu turni alohida ushlaydimi?
2.3. Asos sinf tanlash
class MeningXatom(Exception): ... # ⭐ sukut tanlovQachon boshqasi:
| Asos | Qachon | Misol |
|---|---|---|
Exception |
Odatda | Domen xatolari |
ValueError |
Qiymat yaroqsiz | ValidatsiyaXatosi |
TypeError |
Tur mos emas | Kamdan-kam |
KeyError |
Kalit yo'q | SozlamaTopilmadi |
LookupError |
Qidiruv | Konteyner |
OSError |
Tizim resursi | Fayl, tarmoq |
RuntimeError |
Boshqa ish vaqti | Umumiy |
BaseException |
Hech qachon | — |
O'rnatilgan turdan meros — ehtiyot:
class SozlamaTopilmadi(KeyError):
"""⚠️ str(e) tirnoq bilan chiqadi!"""
e = SozlamaTopilmadi("port")
str(e) # "'port'" ⚠️ tirnoq qo'shildi KeyError.__str__ — repr(args[0]) qaytaradi.
Yechim:
class SozlamaTopilmadi(KeyError):
def __str__(self):
return self.args[0] # ⭐ tirnoqsizKo'p meros ham mumkin:
class SozlamaXatosi(ValueError, KeyError): # ⚠️ ehtiyot
...2.4. Atributlar va konstruktor
class MablagYetarliEmas(Exception):
def __init__(self, kerak: int, bor: int, valyuta: str = "UZS"):
self.kerak = kerak
self.bor = bor
self.valyuta = valyuta
self.yetishmayapti = kerak - bor
super().__init__( # ⭐ SHART
f"{self.yetishmayapti:,} {valyuta} yetishmayapti"
) super().__init__() unutish:
class Yomon(Exception):
def __init__(self, x):
self.x = x # ⚠️ super() yo'q
e = Yomon(5)
str(e) # '5' — hozircha "ishlaydi"
e.args # (5,) Nega ishlaydi? BaseException.__new__ konstruktorga berilgan pozitsion argumentlarni __init__ dan oldin args ga yozib qo'yadi. Shuning uchun super().__init__() chaqirilmasa ham args bo'sh qolmaydi. Lekin ikkita muammo bor:
class Yomon2(Exception):
def __init__(self, kerak, bor):
self.kerak, self.bor = kerak, bor # ⚠️ super() yo'q
str(Yomon2(1000, 300)) # '(1000, 300)' ⚠️ xom kortej
class Yomon3(Exception):
def __init__(self, *, kod): # faqat nomli argument
self.kod = kod
str(Yomon3(kod=404)) # '' ⚠️ BO'SH
Yomon3(kod=404).args # () Xulosa: super().__init__() chaqirmasangiz, str(e) foydalanuvchi uchun yozilgan xabar bo'lmaydi — u yo xom kortej, yo (nomli argumentlarda) bo'sh qator bo'ladi.
args va pickle:
class Yaxshi(Exception):
def __init__(self, kerak, bor):
self.kerak, self.bor = kerak, bor
super().__init__(kerak, bor) # ⭐ args ga pickle istisnoni Sinf(*e.args) bilan qayta yaratadi — shuning uchun args konstruktor argumentlariga mos bo'lishi kerak.
Muammo:
class Xato(Exception):
def __init__(self, kerak, bor):
super().__init__(f"{kerak-bor} yetishmayapti") # ⚠️ 1 argument
pickle.loads(pickle.dumps(Xato(100, 50))) # ❌ TypeErrorYechimlar:
# 1. args ga barcha argumentlar
super().__init__(kerak, bor)
def __str__(self): return f"{self.kerak - self.bor} yetishmayapti"
# 2. __reduce__ bilan
def __reduce__(self):
return (type(self), (self.kerak, self.bor))2.5. __str__ va __repr__
class SorovXatosi(Exception):
def __init__(self, xabar, *, url="", kod=0):
self.url, self.kod = url, kod
super().__init__(xabar)
def __str__(self):
q = [self.args[0]]
if self.kod:
q.append(f"HTTP {self.kod}")
if self.url:
q.append(self.url)
return " | ".join(q)
def __repr__(self):
return (f"{type(self).__name__}({self.args[0]!r}, "
f"url={self.url!r}, kod={self.kod})") Sukut __repr__:
repr(ValueError("a", "b")) # "ValueError('a', 'b')" args dan yasaladi.
2.6. Kutubxona uchun loyihalash
# ⭐ 1. Bitta asos — foydalanuvchi hammasini ushlashi mumkin
class WisarXatosi(Exception):
"""Barcha wisar xatolarining asosi."""
# ⭐ 2. Toifalar
class SozlamaXatosi(WisarXatosi): ...
class TarmoqXatosi(WisarXatosi): ...
class MalumotXatosi(WisarXatosi): ...
# ⭐ 3. Aniq xatolar
class SozlamaTopilmadi(SozlamaXatosi): ...
class SozlamaBuzilgan(SozlamaXatosi): ...
class UlanmadiXato(TarmoqXatosi): ...
class VaqtTugadi(TarmoqXatosi): ...Foydalanuvchi tanlaydi:
except WisarXatosi: # hammasi
except TarmoqXatosi: # toifa
except VaqtTugadi: # aniqO'rnatilgan turlar bilan moslik:
class SozlamaTopilmadi(WisarXatosi, KeyError):
"""⭐ Ikkalasi bilan ham ushlanadi.""" Bu ehtiyotkorlik talab qiladi — MRO va __str__ muammolari.
Modul tuzilishi:
# xatolar.py
__all__ = ["WisarXatosi", "SozlamaXatosi", ...]
# __init__.py
from .xatolar import * # ⭐ ommaviy API2.7. Keng tarqalgan xatolar
# ❌ 1. BaseException dan meros
class MeningXatom(BaseException): ... # ⚠️ Ctrl+C kabi
# ❌ 2. super().__init__() unutish
def __init__(self, a, b): self.a = a # ⚠️ str(e) = '(a, b)' xom kortej
# ❌ 3. Nom "Error" bilan tugamaydi
class Muammo(Exception): ... # ⚠️ PEP 8: XatoError/Error
# ❌ 4. Juda ko'p sinf
class F1Xatosi(Exception): ... # ⚠️ har funksiya uchun
# ❌ 5. Asos sinf yo'q
class XatoA(Exception): ... # ⚠️ bog'lanmagan
class XatoB(Exception): ...
# ❌ 6. Mantiq istisno ichida
class Xato(Exception):
def __init__(self, m):
jurnal.error(m) # ⚠️ yon ta'sir
yubor_xabar(m) # ⚠️
# ❌ 7. O'zgaruvchan sukut
class Xato(Exception):
def __init__(self, teglar=[]): ... # ⚠️3. Tez ma'lumotnoma
Eng oddiy
class MeningXatom(Exception):
"""Nima uchun kerak."""Atributlar bilan
class Xato(Exception):
def __init__(self, kerak, bor):
self.kerak, self.bor = kerak, bor
self.yetishmayapti = kerak - bor
super().__init__(kerak, bor) ⭐ args ga (pickle uchun)
def __str__(self):
return f"{self.yetishmayapti} yetishmayapti"Asos sinf
Exception ⭐ sukut tanlov
ValueError qiymat yaroqsiz
KeyError ⚠️ str(e) tirnoq bilan
OSError tizim resursi
BaseException ❌ hech qachonKutubxona ierarxiyasi
KutubxonaXatosi ⭐ bitta asos
├── ToifaA
│ ├── AniqXato1
│ └── AniqXato2
└── ToifaBXatolar
BaseException dan meros ❌
super().__init__() unutish ❌ str(e) xom kortej yoki bo'sh
args konstruktorga mos emas ⚠️ pickle buziladi
Har funksiya uchun sinf ⚠️ ortiqcha
Istisno ichida yon ta'sir ❌4. Batafsil misollar
Misol 1 — Asoslar va tuzoqlar
"""O'z istisnolaringizni to'g'ri yaratish."""
import pickle
import traceback
print("=== 1. Eng oddiy shakl ===\n")
class MeningXatom(Exception):
"""Uch qator — va to'liq ishlaydi."""
try:
raise MeningXatom("nimadir noto'g'ri")
except MeningXatom as e:
print(f" str(e) = {str(e)!r}")
print(f" repr(e) = {repr(e)}")
print(f" e.args = {e.args}")
print(f" MRO = {[c.__name__ for c in type(e).__mro__]}")
print(f"\n Bir necha argument:")
try:
raise MeningXatom("xabar", 42, {"kalit": "qiymat"})
except MeningXatom as e:
print(f" str(e) = {str(e)!r}")
print(f" e.args = {e.args}")
print(f"\n Argumentsiz:")
try:
raise MeningXatom
except MeningXatom as e:
print(f" str(e) = {str(e)!r}")
print(f" e.args = {e.args}")
print("\n\n=== ⚠️ 2. super().__init__() unutish ===\n")
class Yomon(Exception):
def __init__(self, kerak, bor):
self.kerak = kerak
self.bor = bor # ⚠️ super() YO'Q
class Yaxshi(Exception):
def __init__(self, kerak, bor):
self.kerak = kerak
self.bor = bor
super().__init__(f"{kerak - bor} yetishmayapti") # ⭐
class EngYaxshi(Exception):
def __init__(self, kerak, bor):
self.kerak = kerak
self.bor = bor
self.yetishmayapti = kerak - bor
super().__init__(kerak, bor) # ⭐ args ga
def __str__(self):
return f"{self.yetishmayapti:,} yetishmayapti"
print(f" {'Sinf':<14} {'str(e)':<26} {'e.args':<20} {'pickle'}")
print(" " + "─" * 72)
for Sinf in (Yomon, Yaxshi, EngYaxshi):
e = Sinf(1000, 300)
try:
pickle.loads(pickle.dumps(e))
p = "✅"
except Exception as ex:
p = f"❌ {type(ex).__name__}"
print(f" {Sinf.__name__:<14} {str(e)!r:<26} {str(e.args):<20} {p}")
print(f"""
⚠️ Yomon: str(e) = '(1000, 300)' — xom kortej, foydalanuvchi
nima bo'lganini tushunmaydi (BaseException.__new__
args ni o'zi to'ldirgan, lekin xabar yozilmagan)
⚠️ Yaxshi: pickle BUZILADI — args (1 ta) konstruktorga (2 ta)
mos emas
✅ EngYaxshi: args konstruktor argumentlariga MOS
⭐ SABAB: pickle istisnoni Sinf(*e.args) bilan qayta yaratadi.
""")
print(f" Tekshiruv:")
e = EngYaxshi(1000, 300)
q = pickle.loads(pickle.dumps(e))
print(f" Asl: {e!r}, kerak={e.kerak}, bor={e.bor}")
print(f" Pickle'dan: {q!r}, kerak={q.kerak}, bor={q.bor}")
print(f" str teng: {str(e) == str(q)}")
print(f"\n ⭐ Muqobil — __reduce__:")
class ReduceBilan(Exception):
def __init__(self, kerak, bor):
self.kerak, self.bor = kerak, bor
super().__init__(f"{kerak - bor} yetishmayapti")
def __reduce__(self):
return (type(self), (self.kerak, self.bor)) # ⭐
e = ReduceBilan(1000, 300)
q = pickle.loads(pickle.dumps(e))
print(f" str(e) = {str(e)!r}")
print(f" pickle → {str(q)!r}, kerak={q.kerak} ✅")
print("\n\n=== ⚠️ 3. KeyError dan meros ===\n")
class SozlamaKeyError(KeyError):
"""⚠️ str(e) tirnoq bilan."""
class SozlamaKeyErrorTuzatilgan(KeyError):
"""✅ __str__ qayta aniqlangan."""
def __str__(self):
return self.args[0] if self.args else ""
class SozlamaException(Exception):
"""✅ Exception dan — muammo yo'q."""
print(f" {'Sinf':<32} {'str(e)':<28} {'KeyError mi'}")
print(" " + "─" * 74)
for Sinf in (SozlamaKeyError, SozlamaKeyErrorTuzatilgan,
SozlamaException):
e = Sinf("Sozlama topilmadi: port")
k = isinstance(e, KeyError)
print(f" {Sinf.__name__:<32} {str(e)!r:<28} {k}")
print(f"""
⚠️ KeyError.__str__ — repr(args[0]) qaytaradi:
class KeyError(LookupError):
def __str__(self):
if len(self.args) == 1:
return repr(self.args[0]) ⭐ TIRNOQ qo'shadi
return super().__str__()
⭐ SABAB: KeyError("a b") → xabar "a b" mi yoki kalit 'a b' mi?
repr aniqlik kiritadi.
⚠️ Lekin o'z istisnongizda bu CHALKASH bo'ladi.
""")
print(f" Boshqa o'rnatilgan turlar:")
for Sinf, args in [(ValueError, ("xabar",)), (TypeError, ("xabar",)),
(KeyError, ("xabar",)), (IndexError, ("xabar",)),
(AttributeError, ("xabar",)),
(OSError, (2, "Fayl yo'q"))]:
e = Sinf(*args)
print(f" {Sinf.__name__:<18} str = {str(e)!r}")
print("\n\n=== ⚠️ 4. BaseException dan meros ===\n")
class YomonAsos(BaseException):
"""⚠️ HECH QACHON."""
def ish():
raise YomonAsos("xato")
print(f" except Exception: bilan:")
try:
ish()
print(f" ⚠️")
except Exception:
print(f" ushlandi")
except BaseException as e:
print(f" ⚠️ O'TIB KETDI: {type(e).__name__}")
print(f"""
⚠️ NEGA YOMON:
• except Exception: uni USHLAMAYDI
• Foydalanuvchi kutmaydi
• KeyboardInterrupt bilan bir toifada
• Framework lar to'g'ri ishlamaydi
⭐ BaseException FAQAT:
SystemExit, KeyboardInterrupt, GeneratorExit
(dastur oqimini boshqarish uchun)
⚠️ ISTISNO: agar sizning istisnongiz HAQIQATAN
dastur oqimini to'xtatishi kerak bo'lsa —
lekin bu deyarli hech qachon shunday emas.
""")
print("=== 5. Atributlar va __str__ ===\n")
class SorovXatosi(Exception):
"""⭐ Boy kontekst."""
def __init__(self, xabar: str, *, url: str = "", kod: int = 0,
usul: str = "GET", urinish: int = 1,
davomiylik: float = 0.0):
self.url = url
self.kod = kod
self.usul = usul
self.urinish = urinish
self.davomiylik = davomiylik
super().__init__(xabar)
@property
def xabar(self) -> str:
return self.args[0] if self.args else ""
@property
def qayta_urinsa_boladimi(self) -> bool:
"""⭐ Dasturiy qaror."""
return self.kod in (408, 429, 500, 502, 503, 504)
def __str__(self):
q = [self.xabar]
if self.kod:
q.append(f"HTTP {self.kod}")
if self.usul and self.url:
q.append(f"{self.usul} {self.url}")
if self.urinish > 1:
q.append(f"urinish {self.urinish}")
return " | ".join(q)
def __repr__(self):
return (f"{type(self).__name__}({self.xabar!r}, "
f"url={self.url!r}, kod={self.kod}, "
f"usul={self.usul!r})")
def lugat(self) -> dict:
"""⭐ Serializatsiya uchun."""
return {
"tur": type(self).__name__,
"xabar": self.xabar,
"url": self.url,
"kod": self.kod,
"usul": self.usul,
"urinish": self.urinish,
"davomiylik": round(self.davomiylik, 3),
"qayta_urinsa_boladimi": self.qayta_urinsa_boladimi,
}
XATOLAR = [
SorovXatosi("Xizmat mavjud emas", url="https://api.wisar.uz/xodimlar",
kod=503, urinish=3, davomiylik=12.456),
SorovXatosi("Topilmadi", url="/api/xodim/99", kod=404),
SorovXatosi("Ulanib bo'lmadi", url="https://api.wisar.uz", usul="POST"),
]
for e in XATOLAR:
print(f" str: {e}")
print(f" repr: {e!r}")
print(f" qayta urinish: {e.qayta_urinsa_boladimi}")
print(f" lugat: {e.lugat()}")
print()
print("=== ⭐ 6. Dasturiy ishlov ===\n")
def sorov_bajar(e: SorovXatosi) -> str:
"""⭐ Atributlar asosida qaror."""
if e.qayta_urinsa_boladimi and e.urinish < 5:
return f"🔄 Qayta urinish ({e.urinish + 1}-marta)"
if e.kod == 404:
return "📭 Resurs topilmadi — urinishsiz"
if e.kod in (401, 403):
return "🔒 Autentifikatsiya kerak"
if e.kod >= 500:
return "⚠️ Server xatosi — jurnalga"
if not e.kod:
return "🌐 Tarmoq muammosi — qayta urinish"
return "❓ Noma'lum"
for e in XATOLAR:
print(f" {str(e)[:52]:<54} {sorov_bajar(e)}")
print(f"""
⭐ ATRIBUTLAR NEGA MUHIM:
str(e) — inson uchun
e.kod, e.url — DASTUR uchun
Xabarni tahlil qilish (parsing) ANTIPATTERN:
if "503" in str(e): ❌ mo'rt
if e.kod == 503: ✅
""")
print("=== ⚠️ 7. Keng tarqalgan xatolar ===\n")
print(""" ❌ 1. Yon ta'sir konstruktorda:
class Xato(Exception):
def __init__(self, m):
jurnal.error(m) ⚠️ istisno yaratilganda
xabar_yubor(m) ⚠️ hatto ushlansa ham
super().__init__(m)
⚠️ MUAMMO:
• Istisno yaratilishi ≠ ko'tarilishi
• Testlarda xabar yuboriladi
• pickle da qayta chaqiriladi
✅ Yon ta'sirni except ichida qiling.
❌ 2. O'zgaruvchan sukut:
class Xato(Exception):
def __init__(self, m, teglar=[]): ⚠️ 7.3-dars tuzog'i
self.teglar = teglar
✅ teglar=None → self.teglar = list(teglar or [])
❌ 3. Nom kelishuvi:
class Muammo(Exception) ⚠️
class XatoHolat(Exception) ⚠️
class TolovXatosi(Exception) ✅ (o'zbekcha)
class PaymentError(Exception) ✅ (inglizcha)
⭐ PEP 8: "Error" bilan tugasin (inglizcha loyihalarda)
❌ 4. Juda ko'p sinf:
class YuklashXatosi(Exception)
class TekshirishXatosi(Exception) ⚠️ har funksiya uchun
class OgirishXatosi(Exception)
class SaqlashXatosi(Exception)
✅ Bitta sinf + bosqich atributi:
class QuvurXatosi(Exception):
def __init__(self, m, bosqich): ...
❌ 5. Bog'lanmagan sinflar:
class XatoA(Exception) ⚠️ umumiy asos yo'q
class XatoB(Exception)
✅ class KutubxonaXatosi(Exception)
class XatoA(KutubxonaXatosi)
""")
print(f" Yon ta'sir muammosi namoyishi:\n")
CHAQIRUVLAR = []
class YonTasirli(Exception):
def __init__(self, m):
CHAQIRUVLAR.append(m) # ⚠️ yon ta'sir
super().__init__(m)
print(f" e = YonTasirli('xato') (KO'TARILMAYDI)")
e = YonTasirli("xato")
print(f" CHAQIRUVLAR = {CHAQIRUVLAR} ⚠️ yozildi!")
CHAQIRUVLAR.clear()
q = pickle.loads(pickle.dumps(e))
print(f"\n pickle.loads(...)")
print(f" CHAQIRUVLAR = {CHAQIRUVLAR} ⚠️ yana yozildi!")
print(f"""
⭐ QOIDA: istisno konstruktori — FAQAT ma'lumot saqlash.
Jurnal, xabar, tozalash — except blokida.
""")Natijaning muhim qismi:
=== ⚠️ 2. super().__init__() unutish ===
Sinf str(e) e.args pickle
────────────────────────────────────────────────────────────────────────
Yomon '(1000, 300)' (1000, 300) ✅
Yaxshi '700 yetishmayapti' ('700 yetishmayapti',) ❌ TypeError
EngYaxshi '700 yetishmayapti' (1000, 300) ✅
=== ⚠️ 3. KeyError dan meros ===
Sinf str(e) KeyError mi
──────────────────────────────────────────────────────────────────────────
SozlamaKeyError "'Sozlama topilmadi: port'" True
SozlamaKeyErrorTuzatilgan 'Sozlama topilmadi: port' True
SozlamaException 'Sozlama topilmadi: port' False
=== ⚠️ 4. BaseException dan meros ===
except Exception: bilan:
⚠️ O'TIB KETDI: YomonAsos
=== ⚠️ 7. Keng tarqalgan xatolar ===
e = YonTasirli('xato') (KO'TARILMAYDI)
CHAQIRUVLAR = ['xato'] ⚠️ yozildi!Nima ko'rsatdi: 2.1, 2.3, 2.4, 2.5, 2.7-bo'limlar.
Misol 2 — Kutubxona istisnolari
"""Kutubxona uchun istisno ierarxiyasini loyihalash."""
from __future__ import annotations
import json
from dataclasses import dataclass, field
from datetime import datetime
from typing import Any
print("=== WISAR KUTUBXONASI ISTISNOLARI ===\n")
# ═══ ASOS ═══
class WisarXatosi(Exception):
"""Barcha wisar xatolarining asosi.
⭐ Foydalanuvchi HAMMASINI bitta blok bilan ushlashi mumkin:
except WisarXatosi: ...
"""
#: Foydalanuvchiga ko'rsatiladigan sukut xabar
SUKUT_XABAR: str = "Noma'lum xato"
#: HTTP javob kodi
HTTP_KODI: int = 500
#: Qayta urinish mumkinmi
QAYTA_URINISH: bool = False
def __init__(self, xabar: str = "", **kontekst: Any):
self.kontekst = kontekst
self.vaqt = datetime.now()
super().__init__(xabar or self.SUKUT_XABAR)
@property
def xabar(self) -> str:
return self.args[0] if self.args else self.SUKUT_XABAR
def __str__(self) -> str:
if not self.kontekst:
return self.xabar
k = ", ".join(f"{a}={b!r}" for a, b in self.kontekst.items())
return f"{self.xabar} ({k})"
def __repr__(self) -> str:
k = "".join(f", {a}={b!r}" for a, b in self.kontekst.items())
return f"{type(self).__name__}({self.xabar!r}{k})"
def lugat(self) -> dict[str, Any]:
"""⭐ API javobi uchun."""
return {
"xato": type(self).__name__,
"xabar": self.xabar,
"kod": self.HTTP_KODI,
"qayta_urinish": self.QAYTA_URINISH,
"vaqt": self.vaqt.isoformat(),
**({"kontekst": self.kontekst} if self.kontekst else {}),
}
def json(self) -> str:
return json.dumps(self.lugat(), ensure_ascii=False, default=str)
# ═══ TOIFALAR ═══
class SozlamaXatosi(WisarXatosi):
"""Konfiguratsiya bilan bog'liq."""
SUKUT_XABAR = "Sozlama xatosi"
HTTP_KODI = 500
class TarmoqXatosi(WisarXatosi):
"""Tarmoq va tashqi xizmatlar."""
SUKUT_XABAR = "Tarmoq xatosi"
HTTP_KODI = 503
QAYTA_URINISH = True
class MalumotXatosi(WisarXatosi):
"""Foydalanuvchi ma'lumoti."""
SUKUT_XABAR = "Ma'lumot xatosi"
HTTP_KODI = 400
class RuxsatXatosi(WisarXatosi):
"""Autentifikatsiya va avtorizatsiya."""
SUKUT_XABAR = "Ruxsat yo'q"
HTTP_KODI = 403
class ResursXatosi(WisarXatosi):
"""Tizim resurslari."""
SUKUT_XABAR = "Resurs mavjud emas"
HTTP_KODI = 507
# ═══ ANIQ XATOLAR ═══
class SozlamaTopilmadi(SozlamaXatosi):
def __init__(self, kalit: str, mavjud: list[str] | None = None):
self.kalit = kalit
self.mavjud = list(mavjud or [])
super().__init__(
f"Sozlama topilmadi: {kalit}",
kalit=kalit,
**({"mavjud": self.mavjud[:5]} if self.mavjud else {}),
)
class SozlamaBuzilgan(SozlamaXatosi):
def __init__(self, fayl: str, qator: int = 0, sabab: str = ""):
self.fayl, self.qator = fayl, qator
joy = f":{qator}" if qator else ""
super().__init__(
f"Sozlama fayli buzilgan: {fayl}{joy}"
+ (f" — {sabab}" if sabab else ""),
fayl=fayl, qator=qator,
)
class UlanmadiXato(TarmoqXatosi):
def __init__(self, manzil: str, urinish: int = 1):
self.manzil, self.urinish = manzil, urinish
super().__init__(
f"Ulanib bo'lmadi: {manzil}",
manzil=manzil, urinish=urinish,
)
class VaqtTugadi(TarmoqXatosi):
HTTP_KODI = 504
def __init__(self, amal: str, sekund: float):
self.amal, self.sekund = amal, sekund
super().__init__(
f"Vaqt tugadi: {amal} ({sekund}s)",
amal=amal, sekund=sekund,
)
class TezlikChegarasi(TarmoqXatosi):
HTTP_KODI = 429
def __init__(self, chegara: int, oyna: str = "daqiqa",
kutish: float = 60.0):
self.chegara, self.oyna, self.kutish = chegara, oyna, kutish
super().__init__(
f"Tezlik chegarasi: {chegara}/{oyna}",
chegara=chegara, kutish=kutish,
)
class ValidatsiyaXatosi(MalumotXatosi):
def __init__(self, maydon: str, sabab: str, qiymat: Any = None):
self.maydon, self.sabab, self.qiymat = maydon, sabab, qiymat
super().__init__(
f"{maydon}: {sabab}",
maydon=maydon, **({"qiymat": qiymat}
if qiymat is not None else {}),
)
class TopilmadiXatosi(MalumotXatosi):
HTTP_KODI = 404
def __init__(self, tur: str, id_: Any):
self.tur, self.id = tur, id_
super().__init__(f"{tur} topilmadi: {id_}", tur=tur, id=id_)
class TakrorXatosi(MalumotXatosi):
HTTP_KODI = 409
def __init__(self, tur: str, maydon: str, qiymat: Any):
self.tur, self.maydon, self.qiymat = tur, maydon, qiymat
super().__init__(
f"{tur} allaqachon mavjud: {maydon}={qiymat!r}",
tur=tur, maydon=maydon,
)
class TokenMuddati(RuxsatXatosi):
HTTP_KODI = 401
def __init__(self, tugagan: datetime | None = None):
self.tugagan = tugagan
super().__init__(
"Token muddati tugagan",
**({"tugagan": tugagan.isoformat()} if tugagan else {}),
)
class HuquqYetarliEmas(RuxsatXatosi):
def __init__(self, kerak: str, bor: list[str] | None = None):
self.kerak, self.bor = kerak, list(bor or [])
super().__init__(
f"Huquq kerak: {kerak}",
kerak=kerak, **({"bor": self.bor} if self.bor else {}),
)
class JoyYetarliEmas(ResursXatosi):
def __init__(self, kerak_mb: float, bor_mb: float):
self.kerak_mb, self.bor_mb = kerak_mb, bor_mb
self.yetishmayapti = kerak_mb - bor_mb
super().__init__(
f"Disk joyi yetarli emas: {self.yetishmayapti:.1f} MB kerak",
kerak=kerak_mb, bor=bor_mb,
)
# ═══ IERARXIYA ═══
print("1. Ierarxiya:\n")
def ierarxiya(Sinf: type, chuqurlik: int = 0) -> list[str]:
q = [f"{' ' * chuqurlik}{'└── ' if chuqurlik else ''}"
f"{Sinf.__name__:<22} HTTP {getattr(Sinf, 'HTTP_KODI', '?')}"
f"{' 🔄' if getattr(Sinf, 'QAYTA_URINISH', False) else ''}"]
for a in sorted(Sinf.__subclasses__(), key=lambda c: c.__name__):
q.extend(ierarxiya(a, chuqurlik + 1))
return q
for q in ierarxiya(WisarXatosi):
print(f" {q}")
print("\n\n2. ⭐ Foydalanuvchi tanlaydi:\n")
XATOLAR = [
SozlamaTopilmadi("prot", ["host", "port", "debug", "til"]),
SozlamaBuzilgan("app.json", 12, "Expecting ','"),
UlanmadiXato("db.wisar.uz:5432", urinish=3),
VaqtTugadi("baza so'rovi", 30.0),
TezlikChegarasi(100, "daqiqa", 45.0),
ValidatsiyaXatosi("email", "format noto'g'ri", "notogri"),
TopilmadiXatosi("Xodim", 999),
TakrorXatosi("Xodim", "email", "aziz@wisar.uz"),
TokenMuddati(datetime(2026, 1, 1)),
HuquqYetarliEmas("admin", ["oquvchi", "muharrir"]),
JoyYetarliEmas(500.0, 123.4),
]
print(f" Aniq turlar bilan:\n")
for e in XATOLAR[:4]:
print(f" {type(e).__name__:<20} {e}")
print(f"\n Toifalar bilan:\n")
for Toifa in (SozlamaXatosi, TarmoqXatosi, MalumotXatosi,
RuxsatXatosi, ResursXatosi):
mos = [e for e in XATOLAR if isinstance(e, Toifa)]
print(f" except {Toifa.__name__:<18} → {len(mos)} xato: "
f"{[type(e).__name__ for e in mos]}")
print(f"\n Hammasi:\n")
print(f" except WisarXatosi → {len(XATOLAR)} xato")
print("\n\n3. ⭐ HTTP javoblar:\n")
print(f" {'Istisno':<22} {'HTTP':<7} {'Qayta urin':<12} {'Xabar'}")
print(" " + "─" * 76)
for e in XATOLAR:
print(f" {type(e).__name__:<22} {e.HTTP_KODI:<7} "
f"{'🔄 ha' if e.QAYTA_URINISH else '—':<12} "
f"{str(e)[:32]}")
print("\n\n4. Serializatsiya:\n")
for e in XATOLAR[:3]:
print(f" {type(e).__name__}:")
print(f" {e.json()}")
print()
print("5. ⭐ Dasturiy ishlov:\n")
def ishlov(e: WisarXatosi) -> dict:
"""⭐ Atributlar asosida aniq qaror."""
javob = e.lugat()
if isinstance(e, TezlikChegarasi):
javob["retry_after"] = e.kutish
javob["maslahat"] = f"{e.kutish:.0f} soniyadan keyin urinib ko'ring"
elif isinstance(e, UlanmadiXato):
javob["maslahat"] = (
"Tarmoq ulanishini tekshiring"
if e.urinish >= 3 else "Qayta urinilmoqda"
)
elif isinstance(e, SozlamaTopilmadi) and e.mavjud:
import difflib
yaqin = difflib.get_close_matches(e.kalit, e.mavjud, n=1)
if yaqin:
javob["maslahat"] = f"Balki: {yaqin[0]!r}?"
elif isinstance(e, ValidatsiyaXatosi):
javob["maydon"] = e.maydon
elif isinstance(e, JoyYetarliEmas):
javob["maslahat"] = (
f"{e.yetishmayapti:.0f} MB bo'shatish kerak"
)
elif isinstance(e, TokenMuddati):
javob["maslahat"] = "Qaytadan kiring"
return javob
for e in [XATOLAR[0], XATOLAR[2], XATOLAR[4], XATOLAR[10]]:
j = ishlov(e)
print(f" {type(e).__name__}:")
print(f" HTTP {j['kod']}: {j['xabar']}")
if "maslahat" in j:
print(f" 💡 {j['maslahat']}")
if "retry_after" in j:
print(f" ⏱ Retry-After: {j['retry_after']}")
print()
print("6. ⭐ O'rnatilgan turlar bilan moslik:\n")
class SozlamaKalitYoq(SozlamaXatosi, KeyError):
"""⭐ Ikkalasi bilan ham ushlanadi."""
def __init__(self, kalit: str):
self.kalit = kalit
SozlamaXatosi.__init__(self, f"Kalit yo'q: {kalit}",
kalit=kalit)
def __str__(self):
return SozlamaXatosi.__str__(self) # ⭐ KeyError emas
e = SozlamaKalitYoq("port")
print(f" MRO: {[c.__name__ for c in type(e).__mro__[:5]]}\n")
print(f" {'Ushlash usuli':<28} {'Ishlaydimi'}")
print(" " + "─" * 44)
for Tur in (SozlamaKalitYoq, SozlamaXatosi, WisarXatosi,
KeyError, LookupError, Exception):
print(f" except {Tur.__name__:<20} {isinstance(e, Tur)}")
print(f"\n str(e) = {str(e)!r} ⭐ tirnoqsiz (__str__ tuzatilgan)")
print(f"""
⭐ KO'P MEROS FOYDASI:
• Eski kod: except KeyError: → ishlaydi
• Yangi kod: except SozlamaXatosi: → ham ishlaydi
• Migratsiya oson
⚠️ EHTIYOT:
• MRO murakkablashadi
• __str__ ni qayta aniqlash kerak
• __init__ ni aniq chaqirish kerak
""")Natijaning muhim qismi:
1. Ierarxiya:
WisarXatosi HTTP 500
└── MalumotXatosi HTTP 400
└── TakrorXatosi HTTP 409
└── TopilmadiXatosi HTTP 404
└── ValidatsiyaXatosi HTTP 400
└── ResursXatosi HTTP 507
└── RuxsatXatosi HTTP 403
└── SozlamaXatosi HTTP 500
└── TarmoqXatosi HTTP 503 🔄
└── TezlikChegarasi HTTP 429 🔄
└── UlanmadiXato HTTP 503 🔄
└── VaqtTugadi HTTP 504 🔄
2. ⭐ Foydalanuvchi tanlaydi:
except TarmoqXatosi → 3 xato: ['UlanmadiXato', 'VaqtTugadi',
'TezlikChegarasi']
except WisarXatosi → 11 xato
5. ⭐ Dasturiy ishlov:
SozlamaTopilmadi:
HTTP 500: Sozlama topilmadi: prot
💡 Balki: 'port'?Nima ko'rsatdi: 2.2, 2.4, 2.6-bo'limlar.
Misol 3 — Loyihalash namunalari
"""Turli holatlar uchun istisno loyihalari."""
from __future__ import annotations
import re
from dataclasses import dataclass, field
from datetime import date, datetime
from decimal import Decimal
from enum import Enum
from typing import Any, ClassVar
print("=== 1. Oddiy vs boy istisno ===\n")
class OddiyXato(Exception):
"""✅ Yetarli — atribut kerak emas."""
class BoyXato(Exception):
"""✅ Atributlar dasturiy qaror uchun kerak."""
def __init__(self, xabar: str, *, kod: str, tuzatish: str = ""):
self.kod, self.tuzatish = kod, tuzatish
super().__init__(xabar)
print(""" ⭐ QACHON ODDIY:
• Faqat xabar kerak
• Dasturiy qaror yo'q
• Bir joyda ushlanadi
⭐ QACHON BOY:
• Dastur atributga qarab qaror qiladi
• Foydalanuvchiga tuzatish taklifi
• Serializatsiya (API javob)
• Statistika va guruhlash
""")
print("=== 2. ⭐ Xato kodlari ===\n")
class XatoKodi(str, Enum):
"""⭐ Barqaror kodlar — xabar o'zgarsa ham kod qoladi."""
SOZLAMA_YOQ = "E1001"
SOZLAMA_BUZILGAN = "E1002"
TARMOQ_ULANMADI = "E2001"
TARMOQ_VAQT = "E2002"
MALUMOT_NOTOGRI = "E3001"
MALUMOT_TAKROR = "E3002"
RUXSAT_YOQ = "E4001"
def __str__(self): return self.value
class KodliXato(Exception):
"""⭐ Kod bilan — hujjatlarda havola qilish mumkin."""
KOD: ClassVar[XatoKodi]
def __init__(self, xabar: str = "", **kontekst):
self.kontekst = kontekst
super().__init__(xabar or self.__doc__ or "")
def __str__(self):
return f"[{self.KOD}] {self.args[0]}"
@property
def hujjat_url(self) -> str:
return f"https://docs.wisar.uz/xatolar/{self.KOD}"
class SozlamaYoq(KodliXato):
"""Sozlama fayli topilmadi."""
KOD = XatoKodi.SOZLAMA_YOQ
class TarmoqUlanmadi(KodliXato):
"""Tashqi xizmatga ulanib bo'lmadi."""
KOD = XatoKodi.TARMOQ_ULANMADI
class MalumotTakror(KodliXato):
"""Bunday yozuv allaqachon mavjud."""
KOD = XatoKodi.MALUMOT_TAKROR
for Sinf in (SozlamaYoq, TarmoqUlanmadi, MalumotTakror):
e = Sinf()
print(f" {e}")
print(f" Hujjat: {e.hujjat_url}")
print(f"""
⭐ XATO KODLARI FOYDASI:
• Xabar TARJIMA qilinadi, kod O'ZGARMAYDI
• Foydalanuvchi qidiruvda ishlatadi
• Hujjatga havola
• Qo'llab-quvvatlash xizmati aniq biladi
• Jurnalda guruhlash oson
⭐ Misollar: PostgreSQL (23505), HTTP (404), AWS (AccessDenied)
""")
print("=== 3. ⭐ Ko'p tilli xabarlar ===\n")
class TarjimaliXato(Exception):
"""⭐ Xabar TILGA bog'liq, kod emas."""
XABARLAR: ClassVar[dict[str, str]] = {}
SUKUT_TIL: ClassVar[str] = "uz"
def __init__(self, til: str = "", **params):
self.til = til or self.SUKUT_TIL
self.params = params
super().__init__(self.tarjima(self.til))
def tarjima(self, til: str) -> str:
shablon = self.XABARLAR.get(
til, self.XABARLAR.get(self.SUKUT_TIL, "")
)
try:
return shablon.format(**self.params)
except KeyError:
return shablon
class TokenTugadi(TarjimaliXato):
XABARLAR = {
"uz": "Sessiya muddati tugadi. Qaytadan kiring.",
"ru": "Сессия истекла. Войдите заново.",
"en": "Session expired. Please log in again.",
}
class YetarliEmas(TarjimaliXato):
XABARLAR = {
"uz": "{nima} yetarli emas: {kerak} kerak, {bor} bor",
"ru": "Недостаточно {nima}: нужно {kerak}, есть {bor}",
"en": "Insufficient {nima}: need {kerak}, have {bor}",
}
print(f" Bir xato, uch til:\n")
for til in ("uz", "ru", "en"):
e = TokenTugadi(til)
print(f" {til}: {e}")
print(f"\n Parametrlar bilan:\n")
for til in ("uz", "ru", "en"):
e = YetarliEmas(til, nima="mablag'", kerak="1,000,000",
bor="300,000")
print(f" {til}: {e}")
print(f"""
⭐ TARJIMA STRATEGIYASI:
• Istisno ichida shablon
• Parametrlar alohida
• Til so'rov paytida aniqlanadi
⚠️ MUQOBIL: xabarni istisno TASHQARISIDA tarjima qilish
(gettext, i18n kutubxonalari)
""")
print("=== 4. ⭐ Validatsiya istisnolari ===\n")
@dataclass
class MaydonXatosi:
"""Bitta maydon xatosi."""
yol: str
sabab: str
qiymat: Any = None
kod: str = ""
def __str__(self):
q = f"{self.yol}: {self.sabab}"
if self.qiymat is not None:
q += f" (qiymat: {self.qiymat!r})"
return q
class ValidatsiyaXatosi(Exception):
"""⭐ BIR NECHTA maydon xatosini saqlaydi."""
def __init__(self, xatolar: list[MaydonXatosi] | MaydonXatosi):
if isinstance(xatolar, MaydonXatosi):
xatolar = [xatolar]
self.xatolar = list(xatolar)
super().__init__(f"{len(self.xatolar)} ta validatsiya xatosi")
def __len__(self):
return len(self.xatolar)
def __iter__(self):
return iter(self.xatolar)
def __str__(self):
if len(self.xatolar) == 1:
return str(self.xatolar[0])
return (f"{len(self.xatolar)} ta xato:\n "
+ "\n ".join(str(e) for e in self.xatolar))
def maydonlar(self) -> dict[str, list[str]]:
"""⭐ Frontend uchun: maydon → xatolar."""
natija: dict[str, list[str]] = {}
for e in self.xatolar:
natija.setdefault(e.yol, []).append(e.sabab)
return natija
def lugat(self) -> dict:
return {
"xato": "ValidatsiyaXatosi",
"soni": len(self.xatolar),
"maydonlar": self.maydonlar(),
"tafsilotlar": [
{"yol": e.yol, "sabab": e.sabab, "kod": e.kod}
for e in self.xatolar
],
}
def xodim_tekshir(m: dict) -> dict:
"""⭐ BARCHA xatolarni yig'adi."""
xatolar: list[MaydonXatosi] = []
if not m.get("ism", "").strip():
xatolar.append(MaydonXatosi("ism", "majburiy maydon",
kod="required"))
elif len(m["ism"]) < 2:
xatolar.append(MaydonXatosi("ism", "kamida 2 belgi",
m["ism"], "min_length"))
email = m.get("email", "")
if not email:
xatolar.append(MaydonXatosi("email", "majburiy maydon",
kod="required"))
elif not re.fullmatch(r"[^@\s]+@[^@\s]+\.[a-z]{2,}", email):
xatolar.append(MaydonXatosi("email", "format noto'g'ri",
email, "format"))
maosh = m.get("maosh")
if maosh is None:
xatolar.append(MaydonXatosi("maosh", "majburiy maydon",
kod="required"))
elif not isinstance(maosh, (int, float)):
xatolar.append(MaydonXatosi("maosh", "son bo'lsin",
maosh, "type"))
elif maosh < 500_000:
xatolar.append(MaydonXatosi("maosh", "kamida 500,000",
maosh, "min"))
if "manzil" in m:
manzil = m["manzil"]
if not isinstance(manzil, dict):
xatolar.append(MaydonXatosi("manzil", "obyekt bo'lsin",
manzil, "type"))
else:
if not manzil.get("shahar"):
xatolar.append(MaydonXatosi("manzil.shahar",
"majburiy", kod="required"))
if xatolar:
raise ValidatsiyaXatosi(xatolar)
return m
SINOVLAR = [
{"ism": "Aziz Karimov", "email": "aziz@wisar.uz", "maosh": 8_500_000},
{"ism": "A", "email": "notogri", "maosh": 100},
{"manzil": {"kocha": "Amir Temur"}},
]
for i, m in enumerate(SINOVLAR, 1):
print(f" Sinov {i}:")
try:
xodim_tekshir(m)
print(f" ✅ Muvaffaqiyatli")
except ValidatsiyaXatosi as e:
print(f" ❌ {len(e)} ta xato:")
for x in e:
print(f" • {x}")
print(f" Frontend uchun: {e.maydonlar()}")
print()
print("=== 5. ⭐ Qayta urinish ma'lumoti ===\n")
class QaytaUrinishMumkin(Exception):
"""⭐ Qayta urinish strategiyasini o'zi biladi."""
ENG_KOP_URINISH: ClassVar[int] = 3
ASOSIY_KUTISH: ClassVar[float] = 1.0
def __init__(self, xabar: str, *, urinish: int = 1,
kutish: float | None = None):
self.urinish = urinish
self._kutish = kutish
super().__init__(xabar)
@property
def yana_urinsa_boladimi(self) -> bool:
return self.urinish < self.ENG_KOP_URINISH
@property
def kutish(self) -> float:
"""⭐ Eksponensial kutish."""
if self._kutish is not None:
return self._kutish
return self.ASOSIY_KUTISH * (2 ** (self.urinish - 1))
def keyingi(self) -> "QaytaUrinishMumkin":
"""⭐ Keyingi urinish uchun nusxa."""
return type(self)(self.args[0], urinish=self.urinish + 1,
kutish=self._kutish)
class TarmoqVaqt(QaytaUrinishMumkin):
ENG_KOP_URINISH = 5
ASOSIY_KUTISH = 0.5
class TezlikChegarasi(QaytaUrinishMumkin):
ENG_KOP_URINISH = 3
ASOSIY_KUTISH = 60.0
print(f" {'Istisno':<20} {'Urinish':<10} {'Yana':<8} {'Kutish'}")
print(" " + "─" * 52)
for Sinf in (TarmoqVaqt, TezlikChegarasi):
e = Sinf("xato")
while True:
print(f" {Sinf.__name__:<20} {e.urinish}/"
f"{Sinf.ENG_KOP_URINISH:<8} "
f"{'✅' if e.yana_urinsa_boladimi else '❌':<8} "
f"{e.kutish:.1f}s")
if not e.yana_urinsa_boladimi:
break
e = e.keyingi()
print()
print(f" ⭐ Retry-After sarlavhasi bilan:")
e = TezlikChegarasi("Chegara oshdi", kutish=45.0)
print(f" {e} → Retry-After: {e.kutish:.0f}")
print(f"""
⭐ ISTISNO O'ZI STRATEGIYANI BILADI:
except QaytaUrinishMumkin as e:
if e.yana_urinsa_boladimi:
time.sleep(e.kutish)
raise e.keyingi() ⭐ urinish oshadi
raise
⭐ Har istisno turi o'z sozlamalari bilan.
""")
print("=== 6. ⭐ Istisno fabrikasi ===\n")
def xato_yasa(nom: str, asos: type = Exception, *,
hujjat: str = "", kod: str = "",
http: int = 500) -> type:
"""⭐ Bir xil naqshdagi istisnolarni yaratadi."""
return type(nom, (asos,), {
"__doc__": hujjat or f"{nom} xatosi.",
"KOD": kod or nom.upper(),
"HTTP_KODI": http,
})
class ApiXatosi(Exception):
KOD = "API_ERROR"
HTTP_KODI = 500
# ⭐ Bir necha o'xshash istisno — bir qatorda
NotFound = xato_yasa("NotFound", ApiXatosi, http=404,
hujjat="Resurs topilmadi.")
Conflict = xato_yasa("Conflict", ApiXatosi, http=409,
hujjat="Ziddiyat.")
TooManyRequests = xato_yasa("TooManyRequests", ApiXatosi, http=429,
hujjat="Juda ko'p so'rov.")
Unauthorized = xato_yasa("Unauthorized", ApiXatosi, http=401,
hujjat="Autentifikatsiya kerak.")
print(f" {'Sinf':<20} {'Kod':<20} {'HTTP':<7} {'Hujjat'}")
print(" " + "─" * 68)
for Sinf in (NotFound, Conflict, TooManyRequests, Unauthorized):
print(f" {Sinf.__name__:<20} {Sinf.KOD:<20} "
f"{Sinf.HTTP_KODI:<7} {Sinf.__doc__}")
print(f"\n Ishlatish:")
try:
raise NotFound("Xodim topilmadi: 999")
except ApiXatosi as e:
print(f" except ApiXatosi → {type(e).__name__}: {e}")
print(f" HTTP {e.HTTP_KODI}")
print(f"""
⚠️ FABRIKA — EHTIYOT BILAN:
✅ Ko'p bir xil naqshli istisno
✅ Kod generatsiyasi (OpenAPI dan)
❌ IDE avtoto'ldirish ishlamaydi
❌ mypy tushunmaydi
❌ Manba kodda topib bo'lmaydi
⭐ Odatda ODDIY sinf e'loni yaxshiroq:
class NotFound(ApiXatosi):
HTTP_KODI = 404
""")Natijaning muhim qismi:
=== 2. ⭐ Xato kodlari ===
[E1001] Sozlama fayli topilmadi.
Hujjat: https://docs.wisar.uz/xatolar/E1001
[E2001] Tashqi xizmatga ulanib bo'lmadi.
Hujjat: https://docs.wisar.uz/xatolar/E2001
=== 3. ⭐ Ko'p tilli xabarlar ===
uz: Sessiya muddati tugadi. Qaytadan kiring.
ru: Сессия истекла. Войдите заново.
en: Session expired. Please log in again.
=== 4. ⭐ Validatsiya istisnolari ===
Sinov 2:
❌ 3 ta xato:
• ism: kamida 2 belgi (qiymat: 'A')
• email: format noto'g'ri (qiymat: 'notogri')
• maosh: kamida 500,000 (qiymat: 100)
Frontend uchun: {'ism': ['kamida 2 belgi'], 'email': ["format noto'g'ri"], 'maosh': ['kamida 500,000']}
=== 5. ⭐ Qayta urinish ma'lumoti ===
Istisno Urinish Yana Kutish
────────────────────────────────────────────────────
TarmoqVaqt 1/5 ✅ 0.5s
TarmoqVaqt 2/5 ✅ 1.0s
TarmoqVaqt 5/5 ❌ 8.0sNima ko'rsatdi: 2.2, 2.4, 2.6-bo'limlar.
Misol 4 — Amaliy: to'lov tizimi
"""To'liq istisno loyihasi — real loyihada."""
from __future__ import annotations
import io
import json
import logging
import re
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from decimal import Decimal
from enum import Enum
from typing import Any, ClassVar
print("=== TO'LOV TIZIMI ISTISNOLARI ===\n")
jurnal = logging.getLogger("tolov")
jurnal.setLevel(logging.DEBUG)
_b = io.StringIO()
_h = logging.StreamHandler(_b)
_h.setFormatter(logging.Formatter("%(levelname)-8s %(message)s"))
jurnal.addHandler(_h)
jurnal.propagate = False
class Ogirlik(str, Enum):
"""Xato jiddiyligi."""
PAST = "past" # foydalanuvchi tuzatadi
ORTA = "orta" # qayta urinish
YUQORI = "yuqori" # dasturchi aralashuvi
KRITIK = "kritik" # darhol xabar
def __str__(self): return self.value
# ═══ ASOS ═══
class TolovXatosi(Exception):
"""To'lov tizimining barcha xatolari.
⭐ SINF ATRIBUTLARI — har avlod o'zicha belgilaydi:
KOD, HTTP_KODI, OGIRLIK, QAYTA_URINISH,
FOYDALANUVCHIGA, JURNAL_DARAJASI
"""
KOD: ClassVar[str] = "TOLOV_XATO"
HTTP_KODI: ClassVar[int] = 500
OGIRLIK: ClassVar[Ogirlik] = Ogirlik.YUQORI
QAYTA_URINISH: ClassVar[bool] = False
FOYDALANUVCHIGA: ClassVar[str] = "To'lovda xato yuz berdi"
JURNAL_DARAJASI: ClassVar[int] = logging.ERROR
def __init__(self, xabar: str = "", *, tranzaksiya_id: str = "",
**kontekst: Any):
self.tranzaksiya_id = tranzaksiya_id
self.kontekst = kontekst
self.vaqt = datetime.now()
super().__init__(xabar or self.FOYDALANUVCHIGA)
# ── Ko'rinish ──
@property
def texnik_xabar(self) -> str:
return self.args[0] if self.args else ""
def __str__(self) -> str:
q = [f"[{self.KOD}] {self.texnik_xabar}"]
if self.tranzaksiya_id:
q.append(f"tx={self.tranzaksiya_id}")
if self.kontekst:
q.append(", ".join(f"{k}={v!r}"
for k, v in self.kontekst.items()))
return " | ".join(q)
def __repr__(self) -> str:
return (f"{type(self).__name__}({self.texnik_xabar!r}, "
f"tranzaksiya_id={self.tranzaksiya_id!r})")
# ── API ──
def javob(self) -> tuple[int, dict]:
"""⭐ HTTP javobi — sirlar yo'q."""
tana: dict[str, Any] = {
"xato": {
"kod": self.KOD,
"xabar": self.FOYDALANUVCHIGA,
"ogirlik": str(self.OGIRLIK),
}
}
if self.tranzaksiya_id:
tana["xato"]["tranzaksiya_id"] = self.tranzaksiya_id
if self.QAYTA_URINISH:
tana["xato"]["qayta_urinish"] = True
maslahat = self.maslahat()
if maslahat:
tana["xato"]["maslahat"] = maslahat
return self.HTTP_KODI, tana
def maslahat(self) -> str:
"""⭐ Avlodlar qayta aniqlaydi."""
return ""
def jurnalga(self) -> None:
"""⭐ To'g'ri darajada yozish."""
jurnal.log(
self.JURNAL_DARAJASI, "%s | %s",
type(self).__name__, self,
)
def lugat(self, sirlar: bool = False) -> dict:
m = {
"tur": type(self).__name__,
"kod": self.KOD,
"http": self.HTTP_KODI,
"ogirlik": str(self.OGIRLIK),
"qayta_urinish": self.QAYTA_URINISH,
"vaqt": self.vaqt.isoformat(),
"foydalanuvchiga": self.FOYDALANUVCHIGA,
}
if sirlar:
m["texnik"] = self.texnik_xabar
m["kontekst"] = self.kontekst
m["tranzaksiya_id"] = self.tranzaksiya_id
return m
# ═══ TOIFALAR ═══
class KartaXatosi(TolovXatosi):
"""Karta ma'lumotlari bilan bog'liq."""
KOD = "KARTA_XATO"
HTTP_KODI = 400
OGIRLIK = Ogirlik.PAST
FOYDALANUVCHIGA = "Karta ma'lumotlari noto'g'ri"
JURNAL_DARAJASI = logging.INFO
class MablagXatosi(TolovXatosi):
"""Mablag' bilan bog'liq."""
KOD = "MABLAG_XATO"
HTTP_KODI = 402
OGIRLIK = Ogirlik.PAST
FOYDALANUVCHIGA = "To'lov amalga oshmadi"
JURNAL_DARAJASI = logging.INFO
class ProtsessingXatosi(TolovXatosi):
"""To'lov protsessingi bilan bog'liq."""
KOD = "PROTSESSING_XATO"
HTTP_KODI = 503
OGIRLIK = Ogirlik.ORTA
QAYTA_URINISH = True
FOYDALANUVCHIGA = "To'lov tizimi vaqtincha mavjud emas"
JURNAL_DARAJASI = logging.WARNING
class XavfsizlikXatosi(TolovXatosi):
"""Firibgarlik va xavfsizlik."""
KOD = "XAVFSIZLIK"
HTTP_KODI = 403
OGIRLIK = Ogirlik.KRITIK
FOYDALANUVCHIGA = "Tranzaksiya rad etildi"
JURNAL_DARAJASI = logging.CRITICAL
# ═══ ANIQ XATOLAR ═══
class KartaRaqamiNotogri(KartaXatosi):
KOD = "KARTA_RAQAM"
FOYDALANUVCHIGA = "Karta raqami noto'g'ri"
def __init__(self, raqam: str, sabab: str = "", **kw):
self.oxirgi4 = raqam[-4:] if len(raqam) >= 4 else "****"
super().__init__(
f"Karta raqami yaroqsiz: ****{self.oxirgi4}"
+ (f" ({sabab})" if sabab else ""),
oxirgi4=self.oxirgi4, **kw,
)
def maslahat(self) -> str:
return "Karta raqamini qayta tekshiring (16 raqam)"
class KartaMuddatiTugagan(KartaXatosi):
KOD = "KARTA_MUDDAT"
FOYDALANUVCHIGA = "Karta muddati tugagan"
def __init__(self, muddat: str, **kw):
self.muddat = muddat
super().__init__(f"Karta muddati tugagan: {muddat}",
muddat=muddat, **kw)
def maslahat(self) -> str:
return "Boshqa karta ishlating"
class KartaBloklangan(KartaXatosi):
KOD = "KARTA_BLOK"
HTTP_KODI = 403
OGIRLIK = Ogirlik.ORTA
FOYDALANUVCHIGA = "Karta bloklangan"
JURNAL_DARAJASI = logging.WARNING
def maslahat(self) -> str:
return "Bankingizga murojaat qiling"
class MablagYetarliEmas(MablagXatosi):
KOD = "MABLAG_YOQ"
FOYDALANUVCHIGA = "Hisobda mablag' yetarli emas"
def __init__(self, kerak: Decimal, bor: Decimal,
valyuta: str = "UZS", **kw):
self.kerak, self.bor, self.valyuta = kerak, bor, valyuta
self.yetishmayapti = kerak - bor
super().__init__(
f"Mablag' yetarli emas: {self.yetishmayapti:,.2f} "
f"{valyuta} kerak",
kerak=str(kerak), bor=str(bor), **kw,
)
def maslahat(self) -> str:
return (f"Hisobingizni {self.yetishmayapti:,.0f} "
f"{self.valyuta} ga to'ldiring")
class LimitOshdi(MablagXatosi):
KOD = "LIMIT"
FOYDALANUVCHIGA = "Kunlik limit oshdi"
def __init__(self, limit: Decimal, ishlatilgan: Decimal,
tiklash: datetime | None = None, **kw):
self.limit, self.ishlatilgan = limit, ishlatilgan
self.tiklash = tiklash or (datetime.now() + timedelta(days=1))
super().__init__(
f"Limit oshdi: {ishlatilgan:,.0f}/{limit:,.0f}",
limit=str(limit), **kw,
)
def maslahat(self) -> str:
return f"Limit {self.tiklash:%d.%m %H:%M} da tiklanadi"
class ProtsessingUlanmadi(ProtsessingXatosi):
KOD = "PROTS_ULANISH"
def __init__(self, xizmat: str, urinish: int = 1, **kw):
self.xizmat, self.urinish = xizmat, urinish
super().__init__(
f"Protsessingga ulanib bo'lmadi: {xizmat}",
xizmat=xizmat, urinish=urinish, **kw,
)
def maslahat(self) -> str:
return "Bir necha daqiqadan keyin urinib ko'ring"
class ProtsessingVaqt(ProtsessingXatosi):
KOD = "PROTS_VAQT"
HTTP_KODI = 504
def __init__(self, sekund: float, **kw):
self.sekund = sekund
super().__init__(f"Protsessing javob bermadi ({sekund}s)",
sekund=sekund, **kw)
class FiribgarlikShubhasi(XavfsizlikXatosi):
KOD = "FIRIBGARLIK"
def __init__(self, sabab: str, ball: int = 0, **kw):
self.sabab, self.ball = sabab, ball
super().__init__(
f"Firibgarlik shubhasi: {sabab} (ball: {ball})",
ball=ball, **kw,
)
def maslahat(self) -> str:
return "Qo'llab-quvvatlash xizmatiga murojaat qiling"
class TakroriyTolov(XavfsizlikXatosi):
KOD = "TAKROR"
HTTP_KODI = 409
OGIRLIK = Ogirlik.ORTA
FOYDALANUVCHIGA = "Bu to'lov allaqachon amalga oshirilgan"
JURNAL_DARAJASI = logging.WARNING
def __init__(self, asl_id: str, **kw):
self.asl_id = asl_id
super().__init__(f"Takroriy to'lov: {asl_id}",
asl_id=asl_id, **kw)
def maslahat(self) -> str:
return f"Asl tranzaksiya: {self.asl_id}"
# ═══ IERARXIYA ═══
print("1. Ierarxiya va xossalar:\n")
def daraxt(Sinf, chuqurlik=0):
q = [(chuqurlik, Sinf)]
for a in sorted(Sinf.__subclasses__(), key=lambda c: c.__name__):
q.extend(daraxt(a, chuqurlik + 1))
return q
ogirlik_sarlavha = "Og'irlik"
print(f" {'Sinf':<38} {'Kod':<16} {'HTTP':<6} {ogirlik_sarlavha:<9} {'🔄'}")
print(" " + "─" * 80)
for chuqurlik, Sinf in daraxt(TolovXatosi):
nom = f"{' ' * chuqurlik}{'└─ ' if chuqurlik else ''}{Sinf.__name__}"
print(f" {nom:<38} {Sinf.KOD:<16} {Sinf.HTTP_KODI:<6} "
f"{str(Sinf.OGIRLIK):<9} "
f"{'✅' if Sinf.QAYTA_URINISH else ''}")
print("\n\n2. ⭐ Xatolar va javoblar:\n")
XATOLAR = [
KartaRaqamiNotogri("4242424242424241", "Luhn tekshiruvi",
tranzaksiya_id="TX-001"),
KartaMuddatiTugagan("01/24", tranzaksiya_id="TX-002"),
KartaBloklangan(tranzaksiya_id="TX-003"),
MablagYetarliEmas(Decimal("1500000"), Decimal("320000"),
tranzaksiya_id="TX-004"),
LimitOshdi(Decimal("5000000"), Decimal("5200000"),
tranzaksiya_id="TX-005"),
ProtsessingUlanmadi("uzcard-api", urinish=3,
tranzaksiya_id="TX-006"),
ProtsessingVaqt(30.0, tranzaksiya_id="TX-007"),
FiribgarlikShubhasi("Noodatiy geolokatsiya", ball=87,
tranzaksiya_id="TX-008"),
TakroriyTolov("TX-000", tranzaksiya_id="TX-009"),
]
for e in XATOLAR:
kod, tana = e.javob()
print(f" {type(e).__name__}:")
print(f" Texnik: {e}")
print(f" HTTP {kod}: {tana['xato']['xabar']}")
if "maslahat" in tana["xato"]:
print(f" 💡 Maslahat: {tana['xato']['maslahat']}")
print()
print("3. ⭐ Toifalar bo'yicha ushlash:\n")
TOIFALAR = [
(KartaXatosi, "Karta muammosi"),
(MablagXatosi, "Mablag' muammosi"),
(ProtsessingXatosi, "Tizim muammosi"),
(XavfsizlikXatosi, "Xavfsizlik"),
]
for Toifa, tavsif in TOIFALAR:
mos = [e for e in XATOLAR if isinstance(e, Toifa)]
print(f" except {Toifa.__name__:<20} → {tavsif}")
print(f" {len(mos)} xato: "
f"{[type(e).__name__ for e in mos]}")
print()
print("4. Og'irlik bo'yicha:\n")
ogirlik_guruh: dict[str, list] = {}
for e in XATOLAR:
ogirlik_guruh.setdefault(str(e.OGIRLIK), []).append(e)
for og in ("past", "orta", "yuqori", "kritik"):
ro = ogirlik_guruh.get(og, [])
if not ro:
continue
belgi = {"past": "ℹ️", "orta": "⚠️", "yuqori": "🔴",
"kritik": "🚨"}[og]
print(f" {belgi} {og.upper():<8} ({len(ro)}):")
for e in ro:
print(f" {type(e).__name__:<24} {e.FOYDALANUVCHIGA}")
print()
print("5. ⭐ Jurnal darajalari:\n")
for e in XATOLAR:
e.jurnalga()
print(f" Jurnal ({len(_b.getvalue().rstrip().split(chr(10)))} qator):")
for q in _b.getvalue().rstrip().split("\n"):
print(f" {q[:76]}")
print("\n\n6. ⭐ Qayta urinish mantiqi:\n")
def tolov_urin(xato_yasovchi, maks_urinish: int = 3):
"""⭐ Faqat QAYTA_URINISH=True bo'lganda."""
izlar = []
for urinish in range(1, maks_urinish + 1):
try:
e = xato_yasovchi(urinish)
if e is None:
izlar.append(f"✅ {urinish}-urinishda muvaffaqiyat")
return izlar
raise e
except TolovXatosi as e:
if not e.QAYTA_URINISH:
izlar.append(f"❌ {type(e).__name__} — "
f"qayta urinish FOYDASIZ")
return izlar
izlar.append(f"🔄 {urinish}-urinish: {type(e).__name__}")
izlar.append(f"❌ {maks_urinish} urinish muvaffaqiyatsiz")
return izlar
SENARIYLAR = [
("Vaqtinchalik (3-urinishda tuzaladi)",
lambda n: None if n >= 3 else ProtsessingUlanmadi("api", n)),
("Doimiy tarmoq xatosi",
lambda n: ProtsessingVaqt(30.0)),
("Karta xatosi (qayta urinilmaydi)",
lambda n: KartaMuddatiTugagan("01/24")),
("Mablag' yetarli emas",
lambda n: MablagYetarliEmas(Decimal("1000"), Decimal("100"))),
]
for tavsif, f in SENARIYLAR:
print(f" {tavsif}:")
for q in tolov_urin(f):
print(f" {q}")
print()
print("7. ⭐ Serializatsiya (sirlar bilan/siz):\n")
e = FiribgarlikShubhasi("Noodatiy geolokatsiya: Nigeria", ball=87,
tranzaksiya_id="TX-008",
ip="41.203.x.x", karta="****4242")
print(f" Foydalanuvchiga (sirlarsiz):")
print(f" {json.dumps(e.lugat(sirlar=False), ensure_ascii=False)}")
print(f"\n Jurnalga (sirlar bilan):")
print(f" {json.dumps(e.lugat(sirlar=True), ensure_ascii=False)[:120]}...")
print(f"\n HTTP javob:")
kod, tana = e.javob()
print(f" HTTP {kod}")
print(f" {json.dumps(tana, ensure_ascii=False, indent=6)}")
print(f"""
⭐ BU LOYIHADA:
ASOS SINF (TolovXatosi):
• ClassVar sozlamalar: KOD, HTTP_KODI, OGIRLIK,
QAYTA_URINISH, FOYDALANUVCHIGA, JURNAL_DARAJASI
• javob() — HTTP javobi (sirlarsiz)
• jurnalga() — to'g'ri darajada
• lugat(sirlar=) — ikki ko'rinish
• maslahat() — avlodlar qayta aniqlaydi
TOIFALAR (4 ta):
Karta / Mablag' / Protsessing / Xavfsizlik
→ foydalanuvchi kerakli darajani tanlaydi
ANIQ XATOLAR (9 ta):
Har biri o'z atributlari va maslahati bilan
⭐ NATIJA:
• Foydalanuvchi: tushunarli xabar + maslahat
• Frontend: HTTP kodi + xato kodi
• Dasturchi: to'liq kontekst jurnalda
• Monitoring: og'irlik bo'yicha ogohlantirish
• Qayta urinish: avtomatik va to'g'ri
""")Natijaning muhim qismi:
1. Ierarxiya va xossalar:
Sinf Kod HTTP Og'irlik 🔄
────────────────────────────────────────────────────────────────────────────
TolovXatosi TOLOV_XATO 500 yuqori
└─ KartaXatosi KARTA_XATO 400 past
└─ KartaBloklangan KARTA_BLOK 403 orta
└─ KartaMuddatiTugagan KARTA_MUDDAT 400 past
└─ ProtsessingXatosi PROTSESSING_XATO 503 orta ✅
└─ ProtsessingUlanmadi PROTS_ULANISH 503 orta ✅
2. ⭐ Xatolar va javoblar:
MablagYetarliEmas:
Texnik: [MABLAG_YOQ] Mablag' yetarli emas: 1,180,000.00 UZS kerak | tx=TX-004 | kerak='1500000', bor='320000'
HTTP 402: Hisobda mablag' yetarli emas
💡 Maslahat: Hisobingizni 1,180,000 UZS ga to'ldiring
6. ⭐ Qayta urinish mantiqi:
Vaqtinchalik (3-urinishda tuzaladi):
🔄 1-urinish: ProtsessingUlanmadi
🔄 2-urinish: ProtsessingUlanmadi
✅ 3-urinishda muvaffaqiyat
Karta xatosi (qayta urinilmaydi):
❌ KartaMuddatiTugagan — qayta urinish FOYDASIZNima ko'rsatdi: 2.2, 2.4, 2.6-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "Har funksiya uchun o'z istisnosi" | Ajratilmasa — ortiqcha |
"pass yetadi" |
Docstring yozing |
"super().__init__() ixtiyoriy" |
str(e) xom kortej yoki bo'sh qator bo'ladi |
"args ahamiyatsiz" |
pickle va repr unga tayanadi |
"KeyError dan meros — yaxshi" |
str(e) tirnoq bilan |
"BaseException — asos sinf" |
Hech qachon |
| "Istisno konstruktorida jurnal" | Yon ta'sir |
| "Xabarni tahlil qilish normal" | Atributlar ishlating |
6. Keng tarqalgan xatolar va yechimlari
1. super().__init__() unutish
def __init__(self, kerak, bor): ... # ⚠️ str(e) = '(1000, 300)'
super().__init__(f"...") # ✅ o'qiladigan xabar2. args konstruktorga mos emas
def __init__(self, a, b):
super().__init__(f"{a}-{b}") # ⚠️ pickle buziladi
super().__init__(a, b) # ✅ + __str__3. BaseException dan meros
class X(BaseException): ... # ❌
class X(Exception): ... # ✅4. KeyError dan meros
class X(KeyError): ... # ⚠️ str(e) tirnoq bilan
def __str__(self): return self.args[0] # ✅5. Yon ta'sir konstruktorda
def __init__(self, m):
jurnal.error(m) # ⚠️
super().__init__(m)6. Umumiy asos yo'q
class XatoA(Exception): ... # ⚠️ bog'lanmagan
class KutubxonaXatosi(Exception): ... # ✅ asos
class XatoA(KutubxonaXatosi): ...7. Xabarni tahlil qilish
if "503" in str(e): ... # ⚠️ mo'rt
if e.kod == 503: ... # ✅8. O'zgaruvchan sukut
def __init__(self, teglar=[]): ... # ⚠️
def __init__(self, teglar=None):
self.teglar = list(teglar or []) # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 9.5-dars (o'tilgan):
raise ... from e - 9.7-dars: ierarxiya loyihalash — davomi
- 8-qism: sinflar, meros,
__str__,ClassVar - 17-qism:
pytest.raisesbilan testlash - 20-qism: API xatolari, HTTP kodlari
requests,sqlalchemy,httpx— namunali ierarxiyalar
8. Eng yaxshi amaliyotlar
Kutubxona uchun bitta asos sinf. Foydalanuvchi hammasini ushlashi mumkin.
Exceptiondan meros oling. O'rnatilgan turlardan — faqat asosli sabab bilan.super().__init__()doim chaqiring.argskonstruktorga mos bo'lsin.Atributlar bering. Xabarni tahlil qilish — antipattern.
Docstring yozing.
passemas.Konstruktorda yon ta'sir yo'q. Faqat ma'lumot saqlash.
ClassVarsozlamalar. HTTP kodi, og'irlik, qayta urinish.Ikki ko'rinish. Foydalanuvchi uchun qisqa, jurnal uchun to'liq.
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
1. class X(Exception): pass
print(str(X("a")), X("a").args)
2. class X(Exception):
def __init__(self, a, b): self.a, self.b = a, b
print(repr(str(X(1, 2))))
3. class X(KeyError): pass
print(str(X("xabar")))
4. class X(Exception):
def __init__(self, a, b):
super().__init__(f"{a}+{b}")
import pickle
try: pickle.loads(pickle.dumps(X(1, 2)))
except TypeError: print("TypeError")
5. class X(BaseException): pass
try: raise X()
except Exception: print("ushlandi")
except BaseException: print("o'tdi")
6. class X(Exception): pass
print(X.__mro__[:3])
7. class X(Exception): pass
print(repr(X("a", "b")))
8. class X(Exception):
def __str__(self): return "maxsus"
print(str(X("a")), X("a").args)
9. class X(ValueError): pass
try: raise X("a")
except ValueError as e: print(type(e).__name__)
10. class X(Exception): pass
e = X()
print(str(e), e.args)
11. class X(Exception):
KOD = "E1"
class Y(X):
KOD = "E2"
print(X.KOD, Y.KOD, Y("a").KOD)
12. class X(Exception): pass
print(isinstance(X("a"), Exception), issubclass(X, BaseException))Javoblar
a ('a',)'(1, 2)'—super().__init__()yo'q, lekinBaseException.__new__pozitsion argumentlarniargsga baribir yozgan;str(e)shu xom kortejni ko'rsatadi'xabar'— tirnoq bilanTypeError—args1 ta, konstruktor 2 tao'tdi—BaseException(<class '__main__.X'>, <class 'Exception'>, <class 'BaseException'>)— skript sifatida ishga tushirilganda modul nomi__main__X('a', 'b')maxsus ('a',)X'' ()E1 E2 E2True True
Vazifa 2: Xatolarni tuzating
1. class X(Exception):
def __init__(self, a, b): self.a, self.b = a, b
2. class X(BaseException): pass
3. class X(KeyError): pass
4. class X(Exception):
def __init__(self, m):
jurnal.error(m)
super().__init__(m)
5. class X(Exception):
def __init__(self, teglar=[]): self.teglar = teglar
6. class YuklashXatosi(Exception): pass
class SaqlashXatosi(Exception): pass
7. if "timeout" in str(e): qayta_urin()
8. class X(Exception): pass # docstring yo'qJavoblar
1. super().__init__(a, b) + __str__
2. class X(Exception)
3. __str__ ni qayta aniqlang yoki Exception dan meros
4. jurnal ni except blokiga ko'chiring
5. teglar=None; self.teglar = list(teglar or [])
6. Umumiy asos: class QuvurXatosi(Exception)
7. if isinstance(e, VaqtTugadi): yoki if e.kod == 408:
8. """Nima uchun kerakligi."""Vazifa 3: Kutubxona istisnolari
Yozing:
- Asos sinf + 3 toifa + 8 aniq xato
- Har birida
ClassVarsozlamalar - Atributlar va
maslahat()metodi javob()— HTTP javobilugat(sirlar=)— ikki ko'rinish__all__bilan ommaviy API
Vazifa 4: Istisno tekshiruvchisi
Vosita yozing (AST bilan):
Exceptionavlodlarini topsinsuper().__init__()yo'qliginiBaseExceptiondan merosni- Konstruktorda yon ta'sirni
- Docstring yo'qligini
- Bog'lanmagan sinflarni (umumiy asos yo'q)
Vazifa 5: Validatsiya istisnosi
MaydonXatosidataclassValidatsiyaXatosi— bir nechta maydon__iter__,__len__,maydonlar()- Ichma-ich yo'llar (
manzil.shahar) - Frontend uchun format
ExceptionGroupbilan integratsiya (3.11+)
Vazifa 6: Xato kodlari tizimi
XatoKodienum (E1001 formatda)- Har istisnoda kod
- Hujjat URL generatsiyasi
- Ko'p tilli xabarlar
- Kod bo'yicha qidiruv
- Markdown hujjat generatori
Vazifa 7: O'ylash
Nega Pythonda Exception va BaseException ikkita asos sinf — bitta yetmasmidi?
Javob
Chunki uch istisno turi — SystemExit, KeyboardInterrupt, GeneratorExit — dastur oqimini boshqaradi, xato emas.
1. Muammo: except Exception: nima ushlashi kerak
while True:
try:
ish()
except Exception:
jurnal.exception("Xato")
continue # ⭐ davom etamiz Agar Ctrl+C ham Exception bo'lsa:
# Foydalanuvchi Ctrl+C bosdi
# → KeyboardInterrupt
# → except Exception uni ushlaydi
# → continue
# → ⚠️ CHEKSIZ TSIKL — dasturni to'xtatib bo'lmaydi Shuning uchun KeyboardInterrupt Exception emas.
2. Python 2.4 gacha — bitta ierarxiya
# Python 2.4 va oldin:
Exception
├── SystemExit ⚠️ Exception avlodi
├── KeyboardInterrupt ⚠️
└── StandardError
├── ValueError
└── ...Muammo:
try:
ish()
except Exception: # ⚠️ Ctrl+C ni ham ushlardi
...Shuning uchun dasturchilar yozardi:
except (KeyboardInterrupt, SystemExit):
raise # ⚠️ har joyda takror
except Exception:
...3. PEP 352 (2005) — qayta qurish
Brett Cannon taklif qildi:
BaseException ⭐ YANGI asos
├── SystemExit
├── KeyboardInterrupt
├── GeneratorExit (2.5 da qo'shildi)
└── Exception ⭐ "oddiy" xatolar
├── ValueError
└── ...Natija:
except Exception: # ✅ Ctrl+C o'tadiPython 3 da StandardError ham olib tashlandi — u ortiqcha edi.
4. Uch maxsus istisno
a) SystemExit — sys.exit():
import sys
def main():
if xato:
sys.exit(1) # ⭐ SystemExit ko'taradi
try:
main()
except Exception: # ✅ o'tadi — dastur chiqadi
... sys.exit() — bu istisno, chunki finally bloklar bajarilishi kerak:
try:
sys.exit(1)
finally:
tozala() # ⭐ bajariladib) KeyboardInterrupt — Ctrl+C:
Foydalanuvchi dasturni to'xtatmoqchi — dastur buni hurmat qilishi kerak.
c) GeneratorExit — generator yopilishi:
def gen():
try:
yield 1
yield 2
except GeneratorExit: # ⭐ close() chaqirilganda
tozala()
raise # ⚠️ yutmaslik kerak
g = gen()
next(g)
g.close() # ⭐ GeneratorExit yuboradi Agar generator GeneratorExit ni yutsa:
def yomon():
try:
yield 1
except GeneratorExit:
yield 2 # ❌ RuntimeError: generator ignored5. Amaliy oqibatlar
# ⭐ 1. except Exception — xavfsiz
try:
ish()
except Exception:
jurnal.exception("Xato")
# ⭐ Ctrl+C va sys.exit() O'TADI
# ⚠️ 2. except: — xavfli
try:
ish()
except: # ⚠️ BaseException
...
# ⭐ 3. Ataylab hammasini ushlash
try:
ish()
except BaseException: # ✅ ANIQ niyat
tozala()
raise # ⭐ qayta ko'tarish SHART
# ⭐ 4. Faqat oqim boshqaruvini o'tkazish
try:
ish()
except (KeyboardInterrupt, SystemExit):
raise
except Exception:
...
# ⚠️ Bu ORTIQCHA — except Exception allaqachon o'tkazadi6. Boshqa tillar
| Til | Ierarxiya |
|---|---|
| Python | BaseException → Exception |
| Java | Throwable → Error / Exception |
| C# | Exception (bitta) |
| JavaScript | Error (bitta) |
| Ruby | Exception → StandardError |
Java — juda o'xshash:
Throwable
├── Error ⭐ OutOfMemoryError, StackOverflowError
│ (tuzatib bo'lmaydi)
└── Exception
├── RuntimeException (unchecked)
└── IOException, ... (checked)try {
ish();
} catch (Exception e) { // ⭐ Error o'tadi
...
}Ruby ham:
Exception
├── SystemExit
├── Interrupt # Ctrl+C
├── NoMemoryError
└── StandardError # ⭐ odatiy xatolar
├── ArgumentError
└── ...
begin
ish
rescue # ⭐ SUKUT: StandardError
...
end Ruby eng yaxshi: rescue (turi ko'rsatilmasa) sukut bo'yicha StandardError ni ushlaydi — ya'ni Ctrl+C avtomatik o'tadi.
Python da except: — BaseException. Aksincha bo'lgani yaxshiroq bo'lardi, lekin orqaga moslik.
7. MemoryError va SystemError nega Exception
Qiziq savol:
issubclass(MemoryError, Exception) # True
issubclass(SystemError, Exception) # True
issubclass(RecursionError, Exception) # True Bular ham "tuzatib bo'lmaydigan" xatolar. Nega BaseException emas?
Sabab: ular ba'zan tuzatilishi mumkin:
try:
katta = [0] * 10**12
except MemoryError:
katta = None # ⭐ kichikroq bilan davom etamiz Java da OutOfMemoryError — Error (ushlanmaydi), Python da esa Exception.
8. except* va BaseExceptionGroup
3.11 da bu farq yana muhim bo'ldi:
ExceptionGroup("x", [ValueError()]) # ✅
ExceptionGroup("x", [KeyboardInterrupt()]) # ❌ TypeError
BaseExceptionGroup("x", [KeyboardInterrupt()]) # ✅ ExceptionGroup faqat Exception avlodlarini qabul qiladi.
9. O'z istisnongiz uchun
# ⭐ 99.9% holatda
class MeningXatom(Exception): ...
# ⚠️ BaseException — faqat agar:
# • Dastur oqimini to'xtatishi kerak
# • except Exception: uni USHLAMASLIGI kerak
# • Framework ichki mexanizmi
# Misol (juda kamdan-kam):
class TestSkipped(BaseException):
"""⚠️ Test frameworkida — test kodi uni ushlamasin.""" Bu nazariy misol emas: pytest'ning o'zida pytest.skip() va pytest.fail() ko'taradigan istisnolar OutcomeException(BaseException) dan meros oladi. Sabab aynan shu: test ichidagi except Exception: bloki "testni o'tkazib yubor" signalini tasodifan yutib yubormasligi kerak. Bu — BaseException dan meros olish oqlanadigan kam uchraydigan holatlardan biri: istisno xato emas, boshqaruv oqimi signali.
10. Xulosa
Ikki asos sinf kerak, chekki:
except Exception:xavfsiz bo'lishi kerak —Ctrl+Cvasys.exit()o'tishi shart- Uch istisno — oqim boshqaruvi, xato emas:
SystemExit,KeyboardInterrupt,GeneratorExit finallybloklar bajarilishi kerak — shuning uchunsys.exit()istisno- Java va Ruby ham shunday — bu umumiy dizayn yechimi
Yagona afsus: except: — BaseException ni ushlaydi. Ruby dagidek Exception (ya'ni StandardError) bo'lgani yaxshiroq bo'lardi.
Amaliy qoida:
class MeningXatom(Exception): ... # ⭐ har doim
except Exception: # ⭐ yuqori darajada
except: # ❌ hech qachon
except BaseException: # ⚠️ faqat raise bilanNimani mustahkamlaydi: 2.3, 2.7-bo'limlar.
Xulosa
Bu darsda o'z istisnolaringizni yaratishni o'rgandik.
Eng muhim uch fikr:
Kutubxona uchun bitta asos sinf va toifalar ierarxiyasi.
KutubxonaXatosi→TarmoqXatosi→VaqtTugadi— foydalanuvchi kerakli darajani tanlaydi: hammasi, toifa yoki aniq xato. Asos sinfExceptiondan meros olsin;BaseException— hech qachon, chunkiexcept Exception:uni ushlamaydi.super().__init__()chaqirish majburiy vaargskonstruktorga mos bo'lsin. Unutilsastr(e)o'qiladigan xabar o'rniga xom kortej ('(1000, 300)') yoki, faqat nomli argumentlarda, bo'sh qator bo'ladi;argsmos kelmasapicklebuziladi (u istisnoniSinf(*e.args)bilan qayta yaratadi). Yechim:super().__init__(a, b)+ o'z__str__metodi, yoki__reduce__.Atributlar bering — xabarni tahlil qilish antipattern.
if "503" in str(e)mo'rt;if e.kod == 503ishonchli.ClassVarsozlamalar (HTTP_KODI,QAYTA_URINISH,OGIRLIK) har avlodga o'z xatti-harakatini beradi, va istisno o'zi biladi: qaysi HTTP kodi, qayta urinish kerakmi, foydalanuvchiga nima deyish kerak.
Keyingi darsda istisnolar ierarxiyasini loyihalashni chuqurroq ko'ramiz: standart kutubxona ierarxiyasi, mashhur kutubxonalar namunalari va migratsiya strategiyalari.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!