Mundarija (21)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Bir nechta except bloki
- 2.2. Tuple bilan guruhlash
- 2.3. Istisnolar ierarxiyasi
- 2.4. Xatolarni toifalarga ajratish
- 2.5. ExceptionGroup (3.11+)
- 2.6. Xatolarni yig'ish naqshlari
- 2.7. warnings — istisno bo'lmagan ogohlantirish
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Tartib va ierarxiya
- Misol 2 — ExceptionGroup va except*
- Misol 3 — Toifalarga ajratish strategiyasi
- Misol 4 — Amaliy: validatsiya 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.4-dars: Bir nechta istisno
9-QISM — XATOLAR VA ISTISNOLAR · 4-dars
1. Kirish va motivatsiya
Bu kod hech qachon ikkinchi blokka kirmaydi:
try:
json.loads(matn)
except ValueError:
print("qiymat xatosi")
except json.JSONDecodeError: # ❌ O'LIK KOD
print("JSON xatosi") JSONDecodeError — ValueError avlodi.
Va bu — muammoni yashiradi:
try:
natija = quvur(malumot)
except Exception as e: # ⚠️ hammasi bir xil
return NoneTo'g'ri yondashuv — ierarxiyadan foydalanish:
try:
natija = quvur(malumot)
except (ConnectionError, TimeoutError):
qayta_urin() # ⭐ vaqtinchalik
except (ValueError, TypeError) as e:
jurnal.error("Ma'lumot xatosi: %s", e) # ⭐ doimiy
raise
except OSError as e:
jurnal.critical("Tizim xatosi: %s", e) # ⭐ jiddiy
raiseBu darsda:
- Bir nechta
exceptva tartib qoidasi - Tuple bilan guruhlash
- Istisnolar ierarxiyasi va guruh ushlash
-
ExceptionGroupvaexcept*(3.11+) - Bir vaqtda bir necha xatoni yig'ish
- Xatolarni toifalarga ajratish strategiyasi
2. Nazariya — chuqur tushuntirish
2.1. Bir nechta except bloki
try:
...
except AniqXato: # ⭐ 1
...
except BoshqaXato: # ⭐ 2
...
except UmumiyXato: # ⭐ 3
...Qoidalar:
- Faqat BITTA blok bajariladi
- Tartib bilan tekshiriladi (yuqoridan pastga)
isinstancebo'yicha mos keladi- Birinchi moslik — g'olib
- Hech biri mos kelmasa — yuqoriga uzatiladi
Tartib xatosi:
except ValueError: ... # ⚠️ birinchi
except json.JSONDecodeError: ... # ❌ o'lik kodQoida: aniqdan umumiyga.
2.2. Tuple bilan guruhlash
except (ValueError, TypeError): # ⭐ ikkalasi ham
...
except (ValueError, TypeError) as e:
print(type(e).__name__) # aniq turini bilish mumkinQavs shart:
except ValueError, TypeError: # ❌ SyntaxError (Python 3)
except (ValueError, TypeError): # ✅ Python 2 da except X, e: — as e ma'nosini bergan. Python 3 da bu taqiqlangan.
O'zgaruvchi bilan:
QAYTA_URINISH = (ConnectionError, TimeoutError, OSError)
try:
...
except QAYTA_URINISH: # ⭐ ro'yxatni bir joyda saqlash
...2.3. Istisnolar ierarxiyasi
BaseException
├── SystemExit
├── KeyboardInterrupt
├── GeneratorExit
└── Exception
├── ArithmeticError
│ ├── ZeroDivisionError
│ ├── OverflowError
│ └── FloatingPointError
├── LookupError
│ ├── KeyError
│ └── IndexError
├── OSError (= IOError, EnvironmentError)
│ ├── FileNotFoundError
│ ├── PermissionError
│ ├── FileExistsError
│ ├── IsADirectoryError
│ ├── NotADirectoryError
│ ├── InterruptedError
│ ├── TimeoutError
│ ├── BlockingIOError
│ ├── ChildProcessError
│ └── ConnectionError
│ ├── BrokenPipeError
│ ├── ConnectionAbortedError
│ ├── ConnectionRefusedError
│ └── ConnectionResetError
├── ValueError
│ └── UnicodeError
│ ├── UnicodeDecodeError
│ ├── UnicodeEncodeError
│ └── UnicodeTranslateError
├── TypeError
├── AttributeError
├── NameError
│ └── UnboundLocalError
├── RuntimeError
│ ├── RecursionError
│ └── NotImplementedError
├── ImportError
│ └── ModuleNotFoundError
├── SyntaxError
│ └── IndentationError
│ └── TabError
├── StopIteration
├── StopAsyncIteration
├── AssertionError
├── BufferError
├── EOFError
├── MemoryError
├── ReferenceError
├── SystemError
├── Warning (ierarxiyasi)
└── ExceptionGroup (3.11+)Guruh ushlash:
except LookupError: # KeyError + IndexError
except ArithmeticError: # ZeroDivisionError, Overflow, FloatingPoint
except OSError: # barcha fayl/tarmoq
except ConnectionError: # 4 ta ulanish xatosi
except UnicodeError: # Decode + Encode + TranslateFoydali kombinatsiyalar:
except (ValueError, TypeError): # ma'lumot xatolari
except (OSError, IOError): # ⚠️ IOError == OSError (3.3+)
except (KeyError, IndexError): # ≡ LookupError2.4. Xatolarni toifalarga ajratish
Amaliy strategiya — uch toifa:
# 1. QAYTA URINISH MUMKIN (vaqtinchalik)
VAQTINCHALIK = (ConnectionError, TimeoutError, BlockingIOError)
# 2. MA'LUMOT XATOSI (foydalanuvchi tuzatadi)
MALUMOT = (ValueError, TypeError, KeyError, json.JSONDecodeError)
# 3. TIZIM XATOSI (dasturchi tuzatadi)
TIZIM = (OSError, MemoryError, RuntimeError)try:
ish()
except VAQTINCHALIK:
qayta_urin()
except MALUMOT as e:
return {"xato": str(e)}, 400 # ⭐ HTTP 400
except TIZIM as e:
jurnal.critical(...)
return {"xato": "Ichki xato"}, 500 # ⭐ HTTP 5002.5. ExceptionGroup (3.11+)
Muammo: parallel ishlarda bir nechta xato bo'ladi.
# ⚠️ Python 3.10 va oldin:
xatolar = []
for ish in ishlar:
try:
ish()
except Exception as e:
xatolar.append(e)
if xatolar:
raise xatolar[0] # ⚠️ faqat BIRINCHISIPython 3.11+ (PEP 654):
raise ExceptionGroup("Ishlar bajarilmadi", [
ValueError("1-ish"),
TypeError("2-ish"),
ConnectionError("3-ish"),
]) except* — turlar bo'yicha ajratish:
try:
ish()
except* ValueError as eg:
print(f"{len(eg.exceptions)} ta ValueError")
except* TypeError as eg:
print(f"{len(eg.exceptions)} ta TypeError")Muhim farqlar:
except |
except* |
|
|---|---|---|
| Nechta blok ishlaydi | Bitta | Bir nechta |
as obyekti |
Istisno | ExceptionGroup |
| Guruhga bo'linadi | ||
| Aralashtirish | — | except bilan birga bo'lmaydi |
BaseExceptionGroup:
ExceptionGroup # faqat Exception avlodlari
BaseExceptionGroup # BaseException ham (KeyboardInterrupt)Amaliy ishlatilishi:
async with asyncio.TaskGroup() as tg: # ⭐ 3.11+
tg.create_task(ish1())
tg.create_task(ish2())
# → bir nechta xato bo'lsa ExceptionGroup2.6. Xatolarni yig'ish naqshlari
A) Ro'yxatga yig'ish:
natijalar, xatolar = [], []
for x in malumot:
try:
natijalar.append(ishla(x))
except Exception as e:
xatolar.append((x, e))B) ExceptionGroup bilan (3.11+):
xatolar = []
for x in malumot:
try:
ishla(x)
except Exception as e:
xatolar.append(e)
if xatolar:
raise ExceptionGroup(f"{len(xatolar)} xato", xatolar)C) Kontekst menejeri:
@contextmanager
def yigish():
xatolar = []
yield xatolar
if xatolar:
raise ExceptionGroup("Xatolar", xatolar)2.7. warnings — istisno bo'lmagan ogohlantirish
import warnings
warnings.warn("Bu funksiya eskirgan", DeprecationWarning)Ierarxiya:
Warning
├── UserWarning (sukut)
├── DeprecationWarning ⚠️ sukut bo'yicha yashirin
├── PendingDeprecationWarning
├── SyntaxWarning
├── RuntimeWarning
├── FutureWarning ⭐ foydalanuvchilarga
├── ImportWarning
├── UnicodeWarning
├── BytesWarning
├── ResourceWarning ⚠️ yopilmagan fayllar
└── EncodingWarning (3.10+)Boshqarish:
warnings.simplefilter("error") # ⭐ ogohlantirish → istisno
warnings.simplefilter("ignore")
warnings.filterwarnings("ignore", category=DeprecationWarning)
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
kod()
print(len(w)) # ⭐ ushlangan ogohlantirishlar3. Tez ma'lumotnoma
Bir nechta except
except AniqXato: ... ⭐ 1. aniq
except (A, B) as e: ... ⭐ 2. guruh (qavs SHART)
except OtaSinf: ... ⭐ 3. umumiy
Faqat BITTA blok ishlaydi
Tartib: ANIQDAN UMUMIYGAFoydali guruhlar
LookupError KeyError, IndexError
ArithmeticError ZeroDivisionError, OverflowError, FloatingPointError
OSError FileNotFound, Permission, Connection, Timeout, ...
ConnectionError BrokenPipe, Aborted, Refused, Reset
UnicodeError Decode, Encode, Translate
ImportError ModuleNotFoundError
RuntimeError RecursionError, NotImplementedErrorExceptionGroup (3.11+)
raise ExceptionGroup("xabar", [e1, e2, e3])
try: ...
except* ValueError as eg: ⭐ BIR NECHTA blok ishlashi mumkin
eg.exceptions tuple
except* TypeError as eg: ...
⚠️ except va except* ni ARALASHTIRIB bo'lmaydiToifalar strategiyasi
VAQTINCHALIK = (ConnectionError, TimeoutError) → qayta urin
MALUMOT = (ValueError, TypeError, KeyError) → 400
TIZIM = (OSError, MemoryError) → 5004. Batafsil misollar
Misol 1 — Tartib va ierarxiya
"""Bir nechta except va ierarxiya."""
import builtins
import json
import sys
print("=== ⭐ 1. Tartib qoidasi ===\n")
def togri_tartib(matn: str) -> str:
try:
return f"✅ {json.loads(matn)}"
except json.JSONDecodeError as e: # ⭐ AVLOD
return f"JSONDecodeError: {e.msg}"
except ValueError as e: # ota-sinf
return f"ValueError: {e}"
except TypeError as e:
return f"TypeError: {e}"
def notogri_tartib(matn) -> str:
try:
return f"✅ {json.loads(matn)}"
except ValueError as e: # ⚠️ OTA-SINF avval
return f"ValueError: {e}"
except json.JSONDecodeError as e: # ❌ O'LIK KOD
return f"JSONDecodeError: {e.msg}"
except TypeError as e:
return f"TypeError: {e}"
SINOVLAR = ['{"a": 1}', "{buzilgan}", "not json", 42, None]
print(f" {'Kirish':<18} {'To`g`ri tartib':<30} {'Noto`g`ri'}")
print(" " + "─" * 76)
for m in SINOVLAR:
r1 = togri_tartib(m) if isinstance(m, str) else "—"
if not isinstance(m, str):
try:
r1 = togri_tartib(m)
except TypeError as e:
r1 = f"TypeError: {str(e)[:20]}"
try:
r2 = notogri_tartib(m)
except Exception as e:
r2 = f"❌ {type(e).__name__}"
belgi = "⚠️" if r1.split(":")[0] != r2.split(":")[0] else ""
print(f" {str(m)[:16]:<18} {r1[:28]:<30} {r2[:24]} {belgi}")
print(f"""
⭐ JSONDecodeError MRO:
{[c.__name__ for c in json.JSONDecodeError.__mro__[:4]]}
⚠️ ValueError avval bo'lsa — JSONDecodeError bloki
HECH QACHON ishlamaydi (o'lik kod).
⭐ Linterlar buni topadi:
ruff B014, pylint W0705
""")
print("=== ⭐ 2. Ierarxiya daraxti ===\n")
def daraxt(Sinf, chuqurlik=0, maks=3, korilgan=None):
if korilgan is None:
korilgan = set()
if chuqurlik > maks or Sinf in korilgan:
return []
korilgan.add(Sinf)
q = [f"{' ' * chuqurlik}{'└── ' if chuqurlik else ''}"
f"{Sinf.__name__}"]
avlodlar = sorted(Sinf.__subclasses__(), key=lambda c: c.__name__)
# Faqat o'rnatilgan istisnolar
avlodlar = [c for c in avlodlar
if c.__module__ in ("builtins", "exceptions")]
for a in avlodlar[:8]:
q.extend(daraxt(a, chuqurlik + 1, maks, korilgan))
if len(avlodlar) > 8:
q.append(f"{' ' * (chuqurlik + 1)}└── ... yana "
f"{len(avlodlar) - 8}")
return q
for q in daraxt(BaseException, maks=2):
print(f" {q}")
print(f"\n OSError avlodlari:")
for q in daraxt(OSError, maks=1)[:14]:
print(f" {q}")
print("\n\n=== ⭐ 3. Guruh ushlash ===\n")
GURUHLAR = [
(LookupError, [KeyError("k"), IndexError("i")]),
(ArithmeticError, [ZeroDivisionError("z"), OverflowError("o"),
FloatingPointError("f")]),
(OSError, [FileNotFoundError("f"), PermissionError("p"),
ConnectionResetError("c"), TimeoutError("t")]),
(ConnectionError, [BrokenPipeError("b"), ConnectionRefusedError("r"),
ConnectionResetError("s")]),
(UnicodeError, [UnicodeDecodeError("utf-8", b"\xff", 0, 1, "r"),
UnicodeEncodeError("ascii", "Ў", 0, 1, "r")]),
(ImportError, [ModuleNotFoundError("m")]),
(RuntimeError, [RecursionError("r"), NotImplementedError("n")]),
]
for Ota, avlodlar in GURUHLAR:
nomlar = ", ".join(type(a).__name__ for a in avlodlar)
print(f" except {Ota.__name__}:")
print(f" → {nomlar}")
hammasi = all(isinstance(a, Ota) for a in avlodlar)
print(f" {'✅' if hammasi else '❌'} hammasi ushlanadi\n")
print(f" ⚠️ Taxminlar TEKSHIRUVI:\n")
TAXMINLAR = [
("IOError is OSError", IOError is OSError),
("EnvironmentError is OSError", EnvironmentError is OSError),
("WindowsError bormi", hasattr(builtins, "WindowsError")),
("TimeoutError — OSError", issubclass(TimeoutError, OSError)),
("StopIteration — Exception", issubclass(StopIteration, Exception)),
("KeyboardInterrupt — Exception",
issubclass(KeyboardInterrupt, Exception)),
("SystemExit — Exception", issubclass(SystemExit, Exception)),
("bool — int", issubclass(bool, int)),
("UnicodeDecodeError — ValueError",
issubclass(UnicodeDecodeError, ValueError)),
("ModuleNotFoundError — ImportError",
issubclass(ModuleNotFoundError, ImportError)),
("RecursionError — RuntimeError",
issubclass(RecursionError, RuntimeError)),
]
for tavsif, natija in TAXMINLAR:
print(f" {tavsif:<40} {natija}")
print(f"""
⚠️ MUHIM:
KeyboardInterrupt va SystemExit — Exception EMAS
→ except Exception: ularni ushlamaydi ✅
IOError == OSError (Python 3.3 dan birlashtirilgan)
""")
print("=== 4. Tuple bilan guruhlash ===\n")
def tuple_bilan(f):
try:
return f()
except (ValueError, TypeError, KeyError) as e:
return f"✅ {type(e).__name__}: {str(e)[:24]}"
except Exception as e:
return f"⚠️ ushlanmadi: {type(e).__name__}"
SINOVLAR2 = [
("int('abc')", lambda: int("abc")),
("'a' + 1", lambda: "a" + 1),
("{}['k']", lambda: {}["k"]),
("[1][5]", lambda: [1][5]),
("1/0", lambda: 1 / 0),
]
for kod, f in SINOVLAR2:
print(f" {kod:<16} {tuple_bilan(f)}")
print(f"\n ⭐ O'zgaruvchi bilan (qayta ishlatiladi):\n")
MALUMOT_XATOLARI = (ValueError, TypeError, KeyError, IndexError,
json.JSONDecodeError)
TARMOQ_XATOLARI = (ConnectionError, TimeoutError, BlockingIOError)
TIZIM_XATOLARI = (OSError, MemoryError, SystemError)
def toifali(f):
try:
return ("✅", f())
except MALUMOT_XATOLARI as e:
return ("MA'LUMOT", f"{type(e).__name__}")
except TARMOQ_XATOLARI as e:
return ("TARMOQ", f"{type(e).__name__}")
except TIZIM_XATOLARI as e:
return ("TIZIM", f"{type(e).__name__}")
except Exception as e:
return ("NOMA'LUM", f"{type(e).__name__}")
SINOVLAR3 = [
("int('abc')", lambda: int("abc")),
("{}['k']", lambda: {}["k"]),
("json.loads('{')", lambda: json.loads("{")),
("open('yoq_9999.txt')", lambda: open("yoq_9999.txt")),
("raise ConnectionError", lambda: (_ for _ in ()).throw(
ConnectionError("tarmoq"))),
("raise TimeoutError", lambda: (_ for _ in ()).throw(
TimeoutError("vaqt"))),
("1/0", lambda: 1 / 0),
]
print(f" {'Kod':<26} {'Toifa':<12} {'Tur'}")
print(" " + "─" * 56)
for kod, f in SINOVLAR3:
toifa, tur = toifali(f)
print(f" {kod:<26} {toifa:<12} {tur}")
print(f"""
⚠️ E'TIBOR: TimeoutError — OSError avlodi!
TARMOQ_XATOLARI da bo'lsa ham, agar TIZIM_XATOLARI
avval yozilsa — u yerga tushardi.
⭐ Tartib: aniq guruhlar avval, umumiy keyin.
""")
print("=== ⭐ 5. Qaysi blok ishlaydi ===\n")
def kuzatuv(istisno):
"""Qaysi except bloki ishlashini aniqlaydi."""
izlar = []
try:
raise istisno
except KeyError:
izlar.append("1: KeyError")
except LookupError:
izlar.append("2: LookupError")
except (ValueError, TypeError):
izlar.append("3: (ValueError, TypeError)")
except OSError:
izlar.append("4: OSError")
except Exception:
izlar.append("5: Exception")
return izlar[0] if izlar else "ushlanmadi"
ISTISNOLAR = [
KeyError("k"), IndexError("i"), ValueError("v"), TypeError("t"),
FileNotFoundError("f"), ConnectionError("c"), ZeroDivisionError("z"),
RuntimeError("r"), UnicodeDecodeError("utf-8", b"\xff", 0, 1, "r"),
json.JSONDecodeError("m", "d", 0),
]
print(f" Bloklar tartibi:")
print(f" 1: except KeyError")
print(f" 2: except LookupError")
print(f" 3: except (ValueError, TypeError)")
print(f" 4: except OSError")
print(f" 5: except Exception\n")
print(f" {'Istisno':<26} {'Qaysi blok'}")
print(" " + "─" * 56)
for e in ISTISNOLAR:
print(f" {type(e).__name__:<26} {kuzatuv(e)}")
print(f"""
⭐ IndexError → 2 (LookupError), 1 emas
⭐ UnicodeDecodeError → 3 (ValueError avlodi)
⭐ JSONDecodeError → 3 (ValueError avlodi)
⭐ ConnectionError → 4 (OSError avlodi)
""")
print("=== 6. O'lik kodni topish ===\n")
def olik_kod_tekshir(bloklar: list[type]) -> list[tuple[int, str]]:
"""⭐ Qaysi except bloklari o'lik ekanini aniqlaydi."""
muammolar = []
for i, Joriy in enumerate(bloklar):
for j, Oldingi in enumerate(bloklar[:i]):
if issubclass(Joriy, Oldingi):
muammolar.append((
i,
f"except {Joriy.__name__} (#{i+1}) — o'lik kod: "
f"{Oldingi.__name__} (#{j+1}) uni allaqachon ushlaydi"
))
break
return muammolar
TEKSHIRUVLAR = [
("✅ To'g'ri", [KeyError, LookupError, ValueError, Exception]),
("⚠️ 1", [ValueError, json.JSONDecodeError]),
("⚠️ 2", [Exception, ValueError, KeyError]),
("⚠️ 3", [LookupError, KeyError, IndexError]),
("⚠️ 4", [OSError, FileNotFoundError, ConnectionError]),
("✅ To'g'ri", [json.JSONDecodeError, ValueError, Exception]),
]
for nom, bloklar in TEKSHIRUVLAR:
nomlar = " → ".join(b.__name__ for b in bloklar)
muammolar = olik_kod_tekshir(bloklar)
print(f" {nom}: {nomlar}")
if muammolar:
for _, m in muammolar:
print(f" ❌ {m}")
else:
print(f" ✅ o'lik kod yo'q")
print()Natijaning muhim qismi:
=== ⭐ 1. Tartib qoidasi ===
Kirish To`g`ri tartib Noto`g`ri
────────────────────────────────────────────────────────────────────────────
{"a": 1} ✅ {'a': 1} ✅ {'a': 1}
{buzilgan} JSONDecodeError: Expecting p ValueError: Expecting pr ⚠️
not json JSONDecodeError: Expecting v ValueError: Expecting va ⚠️
=== ⭐ 3. Guruh ushlash ===
except LookupError:
→ KeyError, IndexError
✅ hammasi ushlanadi
⚠️ MUHIM:
KeyboardInterrupt va SystemExit — Exception EMAS
=== ⭐ 5. Qaysi blok ishlaydi ===
Istisno Qaysi blok
────────────────────────────────────────────────────────
KeyError 1: KeyError
IndexError 2: LookupError
UnicodeDecodeError 3: (ValueError, TypeError)
ConnectionError 4: OSError
JSONDecodeError 3: (ValueError, TypeError)
=== 6. O'lik kodni topish ===
⚠️ 1: ValueError → JSONDecodeError
❌ except JSONDecodeError (#2) — o'lik kod: ValueError (#1) uni
allaqachon ushlaydiNima ko'rsatdi: 2.1, 2.2, 2.3-bo'limlar.
Misol 2 — ExceptionGroup va except*
"""Bir vaqtda bir nechta istisno (3.11+)."""
from __future__ import annotations
import sys
import traceback
print(f"=== Python {sys.version_info.major}."
f"{sys.version_info.minor} ===\n")
YANGI = sys.version_info >= (3, 11)
if not YANGI:
print(" ⚠️ ExceptionGroup Python 3.11+ da mavjud")
print(" Quyidagi misollar taqlid qilinadi\n")
print("=== ⚠️ 1. Muammo: faqat birinchi xato ===\n")
def ishlar_eski(malumot: list) -> list:
"""⚠️ Birinchi xatoda to'xtaydi."""
natija = []
for x in malumot:
natija.append(int(x) * 2)
return natija
def ishlar_yigish(malumot: list) -> tuple[list, list]:
"""⚠️ Xatolar yig'iladi, lekin faqat birinchisi ko'tariladi."""
natija, xatolar = [], []
for x in malumot:
try:
natija.append(int(x) * 2)
except (ValueError, TypeError) as e:
xatolar.append(e)
if xatolar:
raise xatolar[0] # ⚠️ qolganlari YO'QOLDI
return natija, xatolar
MALUMOT = [1, "2", "uch", 4, None, "olti", 7, [8]]
print(f" Kirish: {MALUMOT}\n")
try:
ishlar_eski(MALUMOT)
except Exception as e:
print(f" Eski usul: ❌ {type(e).__name__}: {e}")
print(f" ⚠️ Faqat BIRINCHI xato ko'rindi")
try:
ishlar_yigish(MALUMOT)
except Exception as e:
print(f"\n Yig'ish: ❌ {type(e).__name__}: {e}")
print(f" ⚠️ Yana faqat birinchisi ko'tarildi")
print("\n\n=== ⭐ 2. ExceptionGroup ===\n")
if YANGI:
def ishlar_guruh(malumot: list) -> list:
"""⭐ BARCHA xatolarni bir guruhda."""
natija, xatolar = [], []
for i, x in enumerate(malumot):
try:
natija.append(int(x) * 2)
except (ValueError, TypeError) as e:
e.add_note(f"Indeks {i}: {x!r}")
xatolar.append(e)
if xatolar:
raise ExceptionGroup(
f"{len(xatolar)} elementda xato", xatolar
)
return natija
try:
ishlar_guruh(MALUMOT)
except ExceptionGroup as eg:
print(f" ❌ {type(eg).__name__}: {eg.message}")
print(f" Ichida: {len(eg.exceptions)} istisno\n")
for i, e in enumerate(eg.exceptions, 1):
izoh = (f" [{e.__notes__[0]}]"
if hasattr(e, "__notes__") else "")
print(f" {i}. {type(e).__name__}: "
f"{str(e)[:40]}{izoh}")
else:
print(f" ⚠️ Python 3.11+ kerak")
print("\n\n=== ⭐ 3. except* ===\n")
if YANGI:
def guruh_yasa():
raise ExceptionGroup("Aralash xatolar", [
ValueError("qiymat-1"),
TypeError("tur-1"),
ValueError("qiymat-2"),
KeyError("kalit-1"),
TypeError("tur-2"),
ValueError("qiymat-3"),
])
print(f" Guruh: 3 ValueError, 2 TypeError, 1 KeyError\n")
try:
guruh_yasa()
except* ValueError as eg:
print(f" ⭐ except* ValueError: {len(eg.exceptions)} ta")
for e in eg.exceptions:
print(f" - {e}")
except* TypeError as eg:
print(f" ⭐ except* TypeError: {len(eg.exceptions)} ta")
for e in eg.exceptions:
print(f" - {e}")
except* KeyError as eg:
print(f" ⭐ except* KeyError: {len(eg.exceptions)} ta")
print(f"""
⭐ MUHIM FARQ:
except → FAQAT BITTA blok ishlaydi
except* → ⭐ BIR NECHTA blok ishlaydi
Har blok o'z turidagi istisnolarni oladi.
""")
print(f" Bir qismi ushlanmasa:\n")
try:
try:
guruh_yasa()
except* ValueError as eg:
print(f" ValueError: {len(eg.exceptions)} ta ushlandi")
except ExceptionGroup as eg:
print(f" ⭐ Qolgani UZATILDI: {len(eg.exceptions)} ta")
for e in eg.exceptions:
print(f" - {type(e).__name__}: {e}")
else:
print(f" ⚠️ Python 3.11+ kerak")
print("\n\n=== 4. Ichma-ich guruhlar ===\n")
if YANGI:
ichki = ExceptionGroup("Ichki xatolar", [
ValueError("ichki-1"),
TypeError("ichki-2"),
])
tashqi = ExceptionGroup("Tashqi xatolar", [
KeyError("tashqi-1"),
ichki, # ⭐ ichma-ich
IndexError("tashqi-2"),
])
def chiz(eg, chuqurlik=0):
q = []
belgi = " " * chuqurlik
if isinstance(eg, BaseExceptionGroup):
q.append(f"{belgi}📦 {type(eg).__name__}: {eg.message} "
f"({len(eg.exceptions)} ta)")
for e in eg.exceptions:
q.extend(chiz(e, chuqurlik + 1))
else:
q.append(f"{belgi}└─ {type(eg).__name__}: {eg}")
return q
print(f" Tuzilma:")
for q in chiz(tashqi):
print(f" {q}")
print(f"\n ⭐ except* ichma-ich guruhlarni ham topadi:\n")
try:
raise tashqi
except* ValueError as eg:
print(f" ValueError: {len(eg.exceptions)} ta guruh")
for e in eg.exceptions:
print(f" {chiz(e)[0].strip()}")
except* (KeyError, IndexError) as eg:
print(f" KeyError/IndexError: {len(eg.exceptions)} ta")
except* TypeError as eg:
print(f" TypeError: {len(eg.exceptions)} ta")
print(f"""
⭐ except* ichma-ich guruhlarni AVTOMATIK yassilaydi
va faqat mos turlarni oladi.
⭐ subgroup / split metodlari:
""")
faqat_value = tashqi.subgroup(ValueError)
print(f" tashqi.subgroup(ValueError):")
for q in chiz(faqat_value):
print(f" {q}")
mos, qolgan = tashqi.split(ValueError)
print(f"\n tashqi.split(ValueError):")
print(f" mos: {len(mos.exceptions) if mos else 0} ta")
print(f" qolgan: {len(qolgan.exceptions) if qolgan else 0} ta")
else:
print(f" ⚠️ Python 3.11+ kerak")
print("\n\n=== ⚠️ 5. Cheklovlar ===\n")
print(""" ⚠️ 1. except va except* ni ARALASHTIRIB bo'lmaydi:
try: ...
except* ValueError: ...
except TypeError: ... ❌ SyntaxError
⚠️ 2. except* da break/continue/return YO'Q:
for x in ...:
try: ...
except* ValueError:
break ❌ SyntaxError
⚠️ 3. ExceptionGroup BaseException ni qabul qilmaydi:
ExceptionGroup("x", [KeyboardInterrupt()]) ❌ TypeError
BaseExceptionGroup("x", [KeyboardInterrupt()]) ✅
⚠️ 4. Bo'sh guruh mumkin emas:
ExceptionGroup("x", []) ❌ ValueError
⭐ 5. except* BITTA istisnoni ham guruh qiladi:
try:
raise ValueError("bitta")
except* ValueError as eg:
type(eg) ExceptionGroup ⭐
len(eg.exceptions) 1
""")
if YANGI:
print(f" Tekshiruv:\n")
for tavsif, f in [
("ExceptionGroup('x', [])",
lambda: ExceptionGroup("x", [])),
("ExceptionGroup('x', [KeyboardInterrupt()])",
lambda: ExceptionGroup("x", [KeyboardInterrupt()])),
("BaseExceptionGroup('x', [KeyboardInterrupt()])",
lambda: BaseExceptionGroup("x", [KeyboardInterrupt()])),
("ExceptionGroup('x', [ValueError()])",
lambda: ExceptionGroup("x", [ValueError()])),
]:
try:
n = f"✅ {type(f()).__name__}"
except (TypeError, ValueError) as e:
n = f"❌ {type(e).__name__}: {str(e)[:34]}"
print(f" {tavsif:<48} {n}")
print(f"\n Bitta istisno except* bilan:")
try:
raise ValueError("bitta")
except* ValueError as eg:
print(f" type(eg) = {type(eg).__name__}")
print(f" len(eg.exceptions) = {len(eg.exceptions)}")
print(f" eg.exceptions[0] = {eg.exceptions[0]!r}")
print("\n\n=== ⭐ 6. Amaliy: parallel ishlar ===\n")
import concurrent.futures
import time
def ish(n: int) -> str:
"""Ba'zilari xato beradi."""
time.sleep(0.001)
if n % 4 == 0:
raise ValueError(f"Ish {n}: qiymat xatosi")
if n % 5 == 0:
raise TypeError(f"Ish {n}: tur xatosi")
if n % 7 == 0:
raise ConnectionError(f"Ish {n}: tarmoq xatosi")
return f"✅ Ish {n}"
def parallel_eski(ishlar: list[int]):
"""⚠️ Birinchi xato butun ishni to'xtatadi."""
natijalar = []
with concurrent.futures.ThreadPoolExecutor(4) as ex:
for n in ex.map(ish, ishlar):
natijalar.append(n)
return natijalar
def parallel_guruh(ishlar: list[int]):
"""⭐ Barcha xatolar yig'iladi."""
natijalar, xatolar = [], []
with concurrent.futures.ThreadPoolExecutor(4) as ex:
kelajaklar = {ex.submit(ish, n): n for n in ishlar}
for k in concurrent.futures.as_completed(kelajaklar):
n = kelajaklar[k]
try:
natijalar.append(k.result())
except Exception as e:
if YANGI:
e.add_note(f"Ish raqami: {n}")
xatolar.append(e)
if xatolar and YANGI:
raise ExceptionGroup(
f"{len(xatolar)}/{len(ishlar)} ish bajarilmadi", xatolar
)
elif xatolar:
raise xatolar[0]
return natijalar
ISHLAR = list(range(1, 16))
print(f" {len(ISHLAR)} ta parallel ish\n")
try:
parallel_eski(ISHLAR)
except Exception as e:
print(f" Eski usul: ❌ {type(e).__name__}: {e}")
print(f" ⚠️ Qolgan xatolar ko'rinmadi\n")
try:
n = parallel_guruh(ISHLAR)
print(f" ✅ Hammasi bajarildi: {len(n)}")
except Exception as e:
if YANGI and isinstance(e, ExceptionGroup):
print(f" ⭐ ExceptionGroup: {e.message}\n")
try:
raise e
except* ValueError as eg:
print(f" ValueError ({len(eg.exceptions)}):")
for x in eg.exceptions:
print(f" - {x}")
except* TypeError as eg:
print(f" TypeError ({len(eg.exceptions)}):")
for x in eg.exceptions:
print(f" - {x}")
except* ConnectionError as eg:
print(f" ConnectionError ({len(eg.exceptions)}):")
for x in eg.exceptions:
print(f" - {x}")
else:
print(f" ❌ {type(e).__name__}: {e}")
print(f"""
⭐ ExceptionGroup NIMA UCHUN KERAK:
• asyncio.TaskGroup (3.11+)
• concurrent.futures — parallel ishlar
• Ma'lumot validatsiyasi (barcha xatolar)
• Quvurlar — har bosqichdagi xatolar
• Test to'plamlari
⭐ Foydalanuvchi BARCHA muammolarni bir marta ko'radi.
""")Natijaning muhim qismi:
=== ⚠️ 1. Muammo: faqat birinchi xato ===
Eski usul: ❌ ValueError: invalid literal for int() with base 10: 'uch'
⚠️ Faqat BIRINCHI xato ko'rindi
=== ⭐ 2. ExceptionGroup ===
❌ ExceptionGroup: 4 elementda xato
Ichida: 4 istisno
1. ValueError: invalid literal... [Indeks 2: 'uch']
2. TypeError: int() argument must... [Indeks 4: None]
3. ValueError: invalid literal... [Indeks 5: 'olti']
4. TypeError: int() argument must... [Indeks 7: [8]]
=== ⭐ 3. except* ===
⭐ except* ValueError: 3 ta
⭐ except* TypeError: 2 ta
⭐ except* KeyError: 1 ta
⭐ MUHIM FARQ:
except → FAQAT BITTA blok ishlaydi
except* → ⭐ BIR NECHTA blok ishlaydiNima ko'rsatdi: 2.5, 2.6-bo'limlar.
Misol 3 — Toifalarga ajratish strategiyasi
"""Xatolarni toifalab, mos strategiya tanlash."""
from __future__ import annotations
import io
import json
import logging
import random
import time
from dataclasses import dataclass, field
from enum import Enum
from typing import Any, Callable
print("=== XATOLARNI TOIFALASH ===\n")
jurnal = logging.getLogger("toifa")
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 Toifa(str, Enum):
"""⭐ Xato toifalari — har biri o'z strategiyasi bilan."""
VAQTINCHALIK = "vaqtinchalik" # qayta urin
MALUMOT = "malumot" # foydalanuvchi tuzatadi
RUXSAT = "ruxsat" # autentifikatsiya
RESURS = "resurs" # tizim resursi
DASTUR = "dastur" # dasturchi xatosi
NOMALUM = "nomalum"
def __str__(self): return self.value
@dataclass
class Strategiya:
"""Toifa uchun ish tartibi."""
qayta_urin: bool = False
urinishlar: int = 1
jurnal_darajasi: int = logging.ERROR
http_kodi: int = 500
foydalanuvchiga: str = "Ichki xato"
xabar_yubor: bool = False
STRATEGIYALAR: dict[Toifa, Strategiya] = {
Toifa.VAQTINCHALIK: Strategiya(
qayta_urin=True, urinishlar=3,
jurnal_darajasi=logging.WARNING, http_kodi=503,
foydalanuvchiga="Xizmat vaqtincha mavjud emas",
),
Toifa.MALUMOT: Strategiya(
jurnal_darajasi=logging.INFO, http_kodi=400,
foydalanuvchiga="Yuborilgan ma'lumot noto'g'ri",
),
Toifa.RUXSAT: Strategiya(
jurnal_darajasi=logging.WARNING, http_kodi=403,
foydalanuvchiga="Ruxsat yo'q",
),
Toifa.RESURS: Strategiya(
jurnal_darajasi=logging.ERROR, http_kodi=507,
foydalanuvchiga="Tizim resursi yetarli emas",
xabar_yubor=True,
),
Toifa.DASTUR: Strategiya(
jurnal_darajasi=logging.CRITICAL, http_kodi=500,
foydalanuvchiga="Ichki xato",
xabar_yubor=True,
),
Toifa.NOMALUM: Strategiya(
jurnal_darajasi=logging.ERROR, http_kodi=500,
foydalanuvchiga="Kutilmagan xato",
xabar_yubor=True,
),
}
# ⭐ Tartib MUHIM — aniqdan umumiyga
TOIFA_XARITASI: list[tuple[tuple[type, ...], Toifa]] = [
# 1. Eng aniq — tarmoq
((ConnectionError, TimeoutError, BlockingIOError,
InterruptedError), Toifa.VAQTINCHALIK),
# 2. Ruxsat
((PermissionError,), Toifa.RUXSAT),
# 3. Resurs
((MemoryError, RecursionError, BufferError), Toifa.RESURS),
# 4. Ma'lumot
((ValueError, TypeError, KeyError, IndexError,
json.JSONDecodeError, UnicodeError, ArithmeticError),
Toifa.MALUMOT),
# 5. Dastur xatolari
((AttributeError, NameError, ImportError, AssertionError,
NotImplementedError), Toifa.DASTUR),
# 6. Qolgan OS xatolari
((OSError,), Toifa.RESURS),
]
def toifa_aniqla(e: BaseException) -> Toifa:
"""⭐ Istisno turiga qarab toifa."""
for turlar, toifa in TOIFA_XARITASI:
if isinstance(e, turlar):
return toifa
return Toifa.NOMALUM
print("1. Toifalash jadvali:\n")
SINOV_XATOLARI = [
ConnectionResetError("ulanish uzildi"),
TimeoutError("vaqt tugadi"),
PermissionError("ruxsat yo'q"),
MemoryError("xotira tugadi"),
ValueError("noto'g'ri qiymat"),
KeyError("kalit"),
json.JSONDecodeError("Expecting value", "{", 0),
ZeroDivisionError("nolga bo'lish"),
UnicodeDecodeError("utf-8", b"\xff", 0, 1, "invalid"),
AttributeError("atribut yo'q"),
NameError("nom yo'q"),
FileNotFoundError("fayl yo'q"),
IsADirectoryError("papka"),
RuntimeError("noma'lum"),
]
print(f" {'Istisno':<26} {'Toifa':<16} {'HTTP':<7} {'Qayta urin'}")
print(" " + "─" * 62)
for e in SINOV_XATOLARI:
t = toifa_aniqla(e)
s = STRATEGIYALAR[t]
print(f" {type(e).__name__:<26} {str(t):<16} {s.http_kodi:<7} "
f"{'✅ ' + str(s.urinishlar) if s.qayta_urin else '❌'}")
print("\n\n2. ⭐ Strategiya qo'llash:\n")
@dataclass
class Javob:
"""HTTP javobi."""
kod: int
tana: dict[str, Any]
urinishlar: int = 1
def __str__(self):
return f"HTTP {self.kod}: {self.tana}"
class Ishlovchi:
"""⭐ Toifaga qarab strategiya qo'llaydi."""
def __init__(self):
self.xabarlar: list[str] = []
self.statistika: dict[str, int] = {}
def bajar(self, f: Callable, *args, **kwargs) -> Javob:
toifa = None
oxirgi_xato = None
urinish = 0
while True:
urinish += 1
try:
natija = f(*args, **kwargs)
except BaseException as e:
if isinstance(e, (KeyboardInterrupt, SystemExit)):
raise # ⭐ hech qachon yutmaymiz
oxirgi_xato = e
toifa = toifa_aniqla(e)
s = STRATEGIYALAR[toifa]
self.statistika[str(toifa)] = \
self.statistika.get(str(toifa), 0) + 1
jurnal.log(
s.jurnal_darajasi,
"[%s] %s: %s (urinish %d/%d)",
toifa, type(e).__name__, e, urinish, s.urinishlar,
)
if s.qayta_urin and urinish < s.urinishlar:
time.sleep(0.001 * (2 ** (urinish - 1)))
continue
if s.xabar_yubor:
self.xabarlar.append(
f"⚠️ {toifa}: {type(e).__name__}: {e}"
)
return Javob(
kod=s.http_kodi,
tana={"xato": s.foydalanuvchiga,
"toifa": str(toifa)},
urinishlar=urinish,
)
else:
return Javob(200, {"natija": natija},
urinishlar=urinish)
# ═══ SINOV FUNKSIYALARI ═══
HOLAT = {"urinish": 0}
def vaqtinchalik_xato():
"""3-urinishda ishlaydi."""
HOLAT["urinish"] += 1
if HOLAT["urinish"] < 3:
raise ConnectionResetError("ulanish uzildi")
return "✅ ishladi"
def doimiy_vaqtinchalik():
raise TimeoutError("har doim vaqt tugaydi")
def malumot_xatosi():
return json.loads("{buzilgan}")
def ruxsat_xatosi():
raise PermissionError("faylga yozib bo'lmaydi")
def dastur_xatosi():
return None.mavjud_emas
def resurs_xatosi():
raise MemoryError("xotira tugadi")
def muvaffaqiyat():
return {"malumot": [1, 2, 3]}
ish = Ishlovchi()
FUNKSIYALAR = [
("Muvaffaqiyat", muvaffaqiyat),
("Vaqtinchalik (tuzaladi)", vaqtinchalik_xato),
("Vaqtinchalik (doimiy)", doimiy_vaqtinchalik),
("Ma'lumot xatosi", malumot_xatosi),
("Ruxsat xatosi", ruxsat_xatosi),
("Dastur xatosi", dastur_xatosi),
("Resurs xatosi", resurs_xatosi),
]
print(f" {'Holat':<26} {'Javob':<44} {'Urinish'}")
print(" " + "─" * 78)
for nom, f in FUNKSIYALAR:
HOLAT["urinish"] = 0
j = ish.bajar(f)
tana = str(j.tana)[:40]
print(f" {nom:<26} HTTP {j.kod}: {tana:<36} {j.urinishlar}")
print("\n\n3. Statistika:\n")
print(f" {'Toifa':<18} {'Soni':<8} {'Diagramma'}")
print(" " + "─" * 42)
for toifa, n in sorted(ish.statistika.items(), key=lambda x: -x[1]):
print(f" {toifa:<18} {n:<8} {'█' * n}")
print(f"\n Xabar yuborilgan xatolar ({len(ish.xabarlar)}):")
for x in ish.xabarlar:
print(f" {x}")
print("\n\n4. ⭐ Toifalar bo'yicha except:\n")
def toifali_ishlov(f: Callable) -> str:
"""⭐ Toifalar bo'yicha ANIQ except bloklari."""
try:
return f"✅ {f()}"
# ⭐ 1. VAQTINCHALIK — qayta urin
except (ConnectionError, TimeoutError, BlockingIOError) as e:
return f"🔄 Qayta urinish kerak: {type(e).__name__}"
# ⭐ 2. RUXSAT — autentifikatsiya
except PermissionError as e:
return f"🔒 Ruxsat yo'q: {e}"
# ⭐ 3. RESURS — tizim
except (MemoryError, RecursionError) as e:
return f"💾 Resurs tugadi: {type(e).__name__}"
# ⭐ 4. MA'LUMOT — foydalanuvchi
except json.JSONDecodeError as e:
return f"📄 JSON xatosi: {e.msg} (qator {e.lineno})"
except (ValueError, TypeError, KeyError, IndexError) as e:
return f"📝 Ma'lumot xatosi: {type(e).__name__}"
except UnicodeError as e:
return f"🔤 Kodlash xatosi: {type(e).__name__}"
except ArithmeticError as e:
return f"🔢 Hisoblash xatosi: {type(e).__name__}"
# ⭐ 5. DASTUR — bizning xatomiz
except (AttributeError, NameError, ImportError) as e:
jurnal.critical("Dastur xatosi: %s", e)
return f"🐛 Dastur xatosi: {type(e).__name__}"
# ⭐ 6. Qolgan OS xatolari
except OSError as e:
return f"💿 Tizim xatosi: {type(e).__name__} (errno={e.errno})"
# ⭐ 7. Boshqa hammasi
except Exception as e:
jurnal.exception("Kutilmagan xato")
return f"❓ Noma'lum: {type(e).__name__}"
SINOVLAR = [
("muvaffaqiyat", muvaffaqiyat),
("ConnectionError", lambda: doimiy_vaqtinchalik()),
("PermissionError", ruxsat_xatosi),
("MemoryError", resurs_xatosi),
("JSONDecodeError", malumot_xatosi),
("ValueError", lambda: int("abc")),
("UnicodeDecodeError", lambda: b"\xff".decode("utf-8")),
("ZeroDivisionError", lambda: 1 / 0),
("AttributeError", dastur_xatosi),
("FileNotFoundError", lambda: open("yoq_99999.txt")),
("RuntimeError", lambda: (_ for _ in ()).throw(
RuntimeError("noma'lum"))),
]
for nom, f in SINOVLAR:
print(f" {nom:<22} {toifali_ishlov(f)}")
print("\n\n5. ⭐ Toifa xaritasini tekshirish:\n")
def xarita_tekshir() -> list[str]:
"""⭐ O'lik kod va yetishmayotgan turlarni topadi."""
muammolar = []
korilgan: list[type] = []
for i, (turlar, toifa) in enumerate(TOIFA_XARITASI):
for T in turlar:
for K in korilgan:
if issubclass(T, K):
muammolar.append(
f"⚠️ {T.__name__} ({toifa}) — o'lik: "
f"{K.__name__} uni allaqachon ushlaydi"
)
break
korilgan.append(T)
# Qamrab olinmagan muhim turlar
MUHIM = [
StopIteration, GeneratorExit, SystemError, ReferenceError,
EOFError, KeyboardInterrupt, SystemExit,
]
for T in MUHIM:
qamragan = any(
issubclass(T, K) for turlar, _ in TOIFA_XARITASI
for K in turlar
)
if not qamragan:
xavfsiz = issubclass(T, (KeyboardInterrupt, SystemExit,
GeneratorExit))
muammolar.append(
f"{'ℹ️' if xavfsiz else '⚠️'} {T.__name__} "
f"qamrab olinmagan → NOMALUM"
f"{' (ataylab ✅)' if xavfsiz else ''}"
)
return muammolar
for m in xarita_tekshir():
print(f" {m}")
print(f"""
⭐ TOIFALASH STRATEGIYASI AFZALLIKLARI:
1. Har toifa uchun ANIQ ish tartibi
2. Yangi istisno turi → xaritaga bir qator
3. HTTP kodlari markazlashgan
4. Jurnal darajasi mos (INFO/WARNING/CRITICAL)
5. Qayta urinish faqat kerakli joyda
6. Xabar yuborish faqat jiddiy xatolarda
⚠️ TARTIB MUHIM: aniqdan umumiyga
TimeoutError OSError avlodi — agar OSError avval
bo'lsa, u VAQTINCHALIK emas RESURS bo'lardi.
""")
print("\n6. Jurnal:\n")
for q in _b.getvalue().rstrip().split("\n")[:10]:
print(f" {q}")Natijaning muhim qismi:
1. Toifalash jadvali:
Istisno Toifa HTTP Qayta urin
──────────────────────────────────────────────────────────────
ConnectionResetError vaqtinchalik 503 ✅ 3
TimeoutError vaqtinchalik 503 ✅ 3
PermissionError ruxsat 403 ❌
MemoryError resurs 507 ❌
JSONDecodeError malumot 400 ❌
AttributeError dastur 500 ❌
FileNotFoundError resurs 507 ❌
2. ⭐ Strategiya qo'llash:
Holat Javob Urinish
──────────────────────────────────────────────────────────────────────
Vaqtinchalik (tuzaladi) HTTP 200: {'natija': '✅ ishladi'} 3
Vaqtinchalik (doimiy) HTTP 503: {'xato': 'Xizmat vaqtincha mavjud emas', 3
Ma'lumot xatosi HTTP 400: {'xato': "Yuborilgan ma'lumot noto'g'ri" 1
5. ⭐ Toifa xaritasini tekshirish:
ℹ️ KeyboardInterrupt qamrab olinmagan → NOMALUM (ataylab ✅)
ℹ️ SystemExit qamrab olinmagan → NOMALUM (ataylab ✅)Nima ko'rsatdi: 2.3, 2.4-bo'limlar.
Misol 4 — Amaliy: validatsiya tizimi
"""Barcha xatolarni yig'ib, bir marta ko'rsatish."""
from __future__ import annotations
import re
import sys
from contextlib import contextmanager
from dataclasses import dataclass, field
from datetime import date, datetime
from decimal import Decimal, InvalidOperation
from typing import Any, Callable, Iterator
print("=== VALIDATSIYA TIZIMI ===\n")
YANGI = sys.version_info >= (3, 11)
class ValidatsiyaXatosi(Exception):
"""Bitta maydon xatosi."""
def __init__(self, xabar: str, yol: str = "", qiymat: Any = None):
self.yol = yol
self.qiymat = qiymat
super().__init__(f"{yol}: {xabar}" if yol else xabar)
class MajburiyXato(ValidatsiyaXatosi):
"""Maydon yo'q."""
class TurXatosi(ValidatsiyaXatosi):
"""Tur mos emas."""
class QiymatXatosi(ValidatsiyaXatosi):
"""Qiymat yaroqsiz."""
class FormatXatosi(QiymatXatosi):
"""Format mos emas."""
# ═══ XATOLARNI YIG'ISH ═══
class Yiguvchi:
"""⭐ Xatolarni yig'ib, oxirida birga ko'taradi."""
def __init__(self, yol: str = "", maks: int | None = None):
self.yol = yol
self.maks = maks
self.xatolar: list[ValidatsiyaXatosi] = []
@contextmanager
def ushla(self, *turlar: type) -> Iterator[None]:
"""⭐ Bitta amalning xatosini yig'adi."""
turlar = turlar or (ValidatsiyaXatosi,)
try:
yield
except turlar as e:
self.qosh(e)
def qosh(self, e: ValidatsiyaXatosi) -> None:
if self.maks and len(self.xatolar) >= self.maks:
return
self.xatolar.append(e)
def ichki(self, yol: str) -> "Yiguvchi":
"""⭐ Ichma-ich obyekt uchun."""
toliq = f"{self.yol}.{yol}" if self.yol else yol
return Yiguvchi(toliq, self.maks)
def birlashtir(self, boshqa: "Yiguvchi") -> None:
self.xatolar.extend(boshqa.xatolar)
def __bool__(self) -> bool:
return bool(self.xatolar)
def __len__(self) -> int:
return len(self.xatolar)
def kotar(self, xabar: str = "Validatsiya xatolari") -> None:
"""⭐ ExceptionGroup yoki birinchi xato."""
if not self.xatolar:
return
if YANGI:
raise ExceptionGroup(
f"{xabar} ({len(self.xatolar)} ta)", self.xatolar
)
raise self.xatolar[0]
def hisobot(self) -> str:
if not self.xatolar:
return "✅ Xato yo'q"
q = [f"❌ {len(self.xatolar)} ta xato:"]
toifalar: dict[str, list[ValidatsiyaXatosi]] = {}
for e in self.xatolar:
toifalar.setdefault(type(e).__name__, []).append(e)
for tur, ro in sorted(toifalar.items()):
q.append(f" {tur} ({len(ro)}):")
for e in ro:
qiymat = (f" (qiymat: {e.qiymat!r})"
if e.qiymat is not None else "")
q.append(f" • {e}{qiymat}")
return "\n".join(q)
# ═══ TEKSHIRUVCHILAR ═══
def tekshir_majburiy(m: dict, kalit: str, yol: str) -> Any:
if kalit not in m or m[kalit] in (None, ""):
raise MajburiyXato("majburiy maydon", f"{yol}.{kalit}"
if yol else kalit)
return m[kalit]
def tekshir_satr(q: Any, yol: str, *, eng_kam: int = 0,
eng_kop: int | None = None,
naqsh: str = "") -> str:
if not isinstance(q, str):
raise TurXatosi(f"satr kutildi, {type(q).__name__} keldi",
yol, q)
q = q.strip()
if len(q) < eng_kam:
raise QiymatXatosi(f"kamida {eng_kam} belgi ({len(q)} keldi)",
yol, q)
if eng_kop and len(q) > eng_kop:
raise QiymatXatosi(f"ko'pi bilan {eng_kop} belgi", yol, q)
if naqsh and not re.fullmatch(naqsh, q):
raise FormatXatosi("format mos emas", yol, q)
return q
def tekshir_butun(q: Any, yol: str, *, eng_kam: int | None = None,
eng_kop: int | None = None) -> int:
if isinstance(q, bool) or not isinstance(q, (int, str)):
raise TurXatosi(f"butun son kutildi, {type(q).__name__} keldi",
yol, q)
try:
n = int(q)
except ValueError as e:
raise TurXatosi(f"butun songa o'girib bo'lmaydi", yol, q) from e
if eng_kam is not None and n < eng_kam:
raise QiymatXatosi(f">= {eng_kam} bo'lsin", yol, n)
if eng_kop is not None and n > eng_kop:
raise QiymatXatosi(f"<= {eng_kop} bo'lsin", yol, n)
return n
def tekshir_pul(q: Any, yol: str, *, eng_kam: str = "0") -> Decimal:
try:
d = Decimal(str(q).replace(" ", "").replace(",", ""))
except (InvalidOperation, TypeError) as e:
raise TurXatosi("summa emas", yol, q) from e
if d < Decimal(eng_kam):
raise QiymatXatosi(f">= {eng_kam} bo'lsin", yol, d)
return d
def tekshir_sana(q: Any, yol: str, *, kelajak: bool = True) -> date:
if isinstance(q, date):
d = q
else:
for fmt in ("%Y-%m-%d", "%d.%m.%Y"):
try:
d = datetime.strptime(str(q).strip(), fmt).date()
break
except ValueError:
continue
else:
raise FormatXatosi("sana formati YYYY-MM-DD yoki DD.MM.YYYY",
yol, q)
if not kelajak and d > date.today():
raise QiymatXatosi("kelajakda bo'lmasin", yol, d)
return d
def tekshir_email(q: Any, yol: str) -> str:
s = tekshir_satr(q, yol, eng_kam=5, eng_kop=254)
if not re.fullmatch(r"[^@\s]+@[^@\s]+\.[a-zA-Z]{2,}", s):
raise FormatXatosi("email formati noto'g'ri", yol, s)
return s.lower()
# ═══ MODEL VALIDATSIYASI ═══
def xodim_tekshir(m: dict, y: Yiguvchi) -> dict | None:
"""⭐ HAR maydon alohida — barcha xatolar yig'iladi."""
natija: dict[str, Any] = {}
with y.ushla():
natija["id"] = tekshir_butun(
tekshir_majburiy(m, "id", y.yol), f"{y.yol}.id", eng_kam=1
)
with y.ushla():
natija["ism"] = tekshir_satr(
tekshir_majburiy(m, "ism", y.yol), f"{y.yol}.ism",
eng_kam=2, eng_kop=100,
)
with y.ushla():
natija["email"] = tekshir_email(
tekshir_majburiy(m, "email", y.yol), f"{y.yol}.email"
)
with y.ushla():
natija["maosh"] = tekshir_pul(
tekshir_majburiy(m, "maosh", y.yol), f"{y.yol}.maosh",
eng_kam="500000",
)
if "yosh" in m:
with y.ushla():
natija["yosh"] = tekshir_butun(
m["yosh"], f"{y.yol}.yosh", eng_kam=16, eng_kop=100
)
if "ishga_kirgan" in m:
with y.ushla():
natija["ishga_kirgan"] = tekshir_sana(
m["ishga_kirgan"], f"{y.yol}.ishga_kirgan",
kelajak=False,
)
# ⭐ Ichma-ich obyekt
if "manzil" in m:
ichki = y.ichki("manzil")
manzil = manzil_tekshir(m["manzil"], ichki)
y.birlashtir(ichki)
if manzil:
natija["manzil"] = manzil
return natija if not y else None
def manzil_tekshir(m: Any, y: Yiguvchi) -> dict | None:
if not isinstance(m, dict):
y.qosh(TurXatosi(f"obyekt kutildi, {type(m).__name__} keldi",
y.yol, m))
return None
natija = {}
with y.ushla():
natija["shahar"] = tekshir_satr(
tekshir_majburiy(m, "shahar", y.yol), f"{y.yol}.shahar",
eng_kam=2,
)
with y.ushla():
natija["kocha"] = tekshir_satr(
tekshir_majburiy(m, "kocha", y.yol), f"{y.yol}.kocha",
eng_kam=3,
)
if "indeks" in m:
with y.ushla():
natija["indeks"] = tekshir_satr(
m["indeks"], f"{y.yol}.indeks", naqsh=r"\d{6}"
)
return natija if not y else None
# ═══ SINOVLAR ═══
XODIMLAR = [
# ✅ To'liq to'g'ri
{
"id": 1, "ism": "Aziz Karimov", "email": "aziz@wisar.uz",
"maosh": "8500000", "yosh": 30, "ishga_kirgan": "2023-03-15",
"manzil": {"shahar": "Toshkent", "kocha": "Amir Temur 12",
"indeks": "100000"},
},
# ⚠️ Ko'p xato
{
"id": "xato", "ism": "A", "email": "notogri",
"maosh": "kam", "yosh": 200, "ishga_kirgan": "2099-01-01",
"manzil": {"shahar": "T", "indeks": "abc"},
},
# ⚠️ Majburiy maydonlar yo'q
{"yosh": 25},
# ⚠️ Manzil noto'g'ri tur
{
"id": 3, "ism": "Bobur Aliyev", "email": "bobur@wisar.uz",
"maosh": 9500000, "manzil": "Toshkent",
},
]
print("1. Har xodim alohida:\n")
for i, xodim in enumerate(XODIMLAR, 1):
y = Yiguvchi(yol=f"xodim[{i}]")
natija = xodim_tekshir(xodim, y)
print(f" ┌─ Xodim {i}")
if natija:
print(f" │ ✅ Muvaffaqiyatli")
for k, v in natija.items():
if k != "manzil":
print(f" │ {k:<14} {v!r}")
else:
print(f" │ {k:<14} {v}")
else:
for q in y.hisobot().split("\n"):
print(f" │ {q}")
print(f" └{'─' * 60}\n")
print("\n2. ⭐ Barcha xodimlarni birga:\n")
umumiy = Yiguvchi()
natijalar = []
for i, xodim in enumerate(XODIMLAR, 1):
y = Yiguvchi(yol=f"xodim[{i}]")
n = xodim_tekshir(xodim, y)
if n:
natijalar.append(n)
umumiy.birlashtir(y)
print(f" ✅ Yuklandi: {len(natijalar)}/{len(XODIMLAR)}")
print(f" ❌ Xatolar: {len(umumiy)}\n")
print(f" Xatolar toifalari:")
toifalar: dict[str, int] = {}
for e in umumiy.xatolar:
toifalar[type(e).__name__] = toifalar.get(type(e).__name__, 0) + 1
for tur, n in sorted(toifalar.items(), key=lambda x: -x[1]):
print(f" {tur:<20} {n:>3} {'█' * n}")
print("\n\n3. ⭐ ExceptionGroup bilan ko'tarish:\n")
if YANGI:
try:
umumiy.kotar("Xodimlar validatsiyasi")
except* MajburiyXato as eg:
print(f" 📋 Majburiy maydonlar ({len(eg.exceptions)}):")
for e in eg.exceptions[:4]:
print(f" • {e}")
except* TurXatosi as eg:
print(f"\n 🔤 Tur xatolari ({len(eg.exceptions)}):")
for e in eg.exceptions[:4]:
print(f" • {e}")
except* FormatXatosi as eg:
print(f"\n 📐 Format xatolari ({len(eg.exceptions)}):")
for e in eg.exceptions:
print(f" • {e}")
except* QiymatXatosi as eg:
print(f"\n 📊 Qiymat xatolari ({len(eg.exceptions)}):")
for e in eg.exceptions:
print(f" • {e}")
else:
print(f" ⚠️ Python 3.11+ kerak — birinchi xato:")
try:
umumiy.kotar()
except ValidatsiyaXatosi as e:
print(f" {type(e).__name__}: {e}")
print("\n\n4. Xato chegarasi:\n")
for maks in [None, 5, 3, 1]:
y = Yiguvchi(yol="xodim", maks=maks)
xodim_tekshir(XODIMLAR[1], y)
print(f" maks={str(maks):<6} → {len(y)} xato yig'ildi")
print("\n\n5. ⭐ Yo'l (path) bilan xatolar:\n")
y = Yiguvchi(yol="sorov")
xodim_tekshir(XODIMLAR[1], y)
print(f" Ichma-ich yo'llar:")
for e in y.xatolar:
print(f" {e.yol:<32} {type(e).__name__}")
print(f"""
⭐ YO'L (path) FOYDASI:
• Foydalanuvchi ANIQ qayerda xato ekanini biladi
• Frontend maydonni belgilashi mumkin
• Ichma-ich obyektlarda ham ishlaydi
⭐ pydantic, marshmallow, cerberus — hammasi shunday
""")
print("\n6. Xulosa:\n")
print(f""" ⭐ BU TIZIMDA:
ISTISNO IERARXIYASI:
ValidatsiyaXatosi
├── MajburiyXato
├── TurXatosi
└── QiymatXatosi
└── FormatXatosi
⭐ Ierarxiya tufayli:
except QiymatXatosi: → FormatXatosi ham
except ValidatsiyaXatosi: → hammasi
XATOLARNI YIG'ISH:
Yiguvchi.ushla() — kontekst menejeri
Har maydon alohida → barcha xatolar ko'rinadi
ICHMA-ICH:
y.ichki("manzil") → "xodim.manzil.shahar"
EXCEPTIONGROUP:
except* bilan toifalar bo'yicha ajratish
Foydalanuvchi barcha muammoni BIR MARTA ko'radi
⚠️ ANTIPATTERN (birinchi xatoda to'xtash):
for maydon in maydonlar:
tekshir(maydon) ⚠️ birinchi xatoda to'xtaydi
⚠️ foydalanuvchi 5 marta yuboradi
""")Natijaning muhim qismi:
1. Har xodim alohida:
┌─ Xodim 2
│ ❌ 9 ta xato:
│ FormatXatosi (2):
│ • xodim[2].manzil.indeks: format mos emas (qiymat: 'abc')
│ • xodim[2].manzil.indeks: format mos emas (qiymat: 'abc')
│ MajburiyXato (1):
│ • xodim[2].manzil.kocha: majburiy maydon
│ QiymatXatosi (4):
│ • xodim[2].ism: kamida 2 belgi (1 keldi)
│ • xodim[2].yosh: <= 100 bo'lsin (qiymat: 200)
│ TurXatosi (2):
│ • xodim[2].id: butun songa o'girib bo'lmaydi
3. ⭐ ExceptionGroup bilan ko'tarish:
📋 Majburiy maydonlar (5):
• xodim[3].id: majburiy maydon
• xodim[3].ism: majburiy maydon
🔤 Tur xatolari (3):
• xodim[2].id: butun songa o'girib bo'lmaydiNima ko'rsatdi: 2.3, 2.5, 2.6-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
"Bir necha except — hammasi ishlaydi" |
Faqat bitta |
| "Tartib ahamiyatsiz" | Avlod avval bo'lishi kerak |
"except A, B: ishlaydi" |
SyntaxError; qavs kerak |
"IOError va OSError — turli" |
Bir xil (3.3 dan) |
"TimeoutError — tarmoq xatosi" |
OSError avlodi |
"except* — except ning sinonimi" |
Bir nechta blok ishlaydi |
"ExceptionGroup — oddiy ro'yxat" |
Ierarxik, split/subgroup bor |
| "Birinchi xatoda to'xtash kerak" | Validatsiyada — hammasini yig'ing |
6. Keng tarqalgan xatolar va yechimlari
1. Noto'g'ri tartib
except ValueError: ...
except JSONDecodeError: ... # ❌ o'lik kod
# ✅ teskari2. Qavssiz tuple
except ValueError, TypeError: # ❌ SyntaxError
except (ValueError, TypeError): # ✅3. Juda keng birinchi blok
except Exception: ... # ⚠️ birinchi
except ValueError: ... # ❌ o'lik4. OSError avlodlarini unutish
except (ConnectionError, OSError): # ⚠️ ConnectionError ortiqcha
except OSError: # ✅ yoki teskari tartib5. Birinchi xatoda to'xtash
for x in malumot:
tekshir(x) # ⚠️ birinchi xatoda to'xtaydi
# ✅ xatolarni yig'ing6. except* va except aralashmasi
except* ValueError: ...
except TypeError: ... # ❌ SyntaxError7. ExceptionGroup da BaseException
ExceptionGroup("x", [KeyboardInterrupt()]) # ❌
BaseExceptionGroup("x", [KeyboardInterrupt()]) # ✅8. Toifalarda tartib xatosi
except OSError: ... # ⚠️ TimeoutError ham
except TimeoutError: ... # ❌ o'lik7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 9.2-9.3-darslar (o'tilgan):
try/except/finally - 9.6-9.7: o'z istisnolaringiz, ierarxiya
- 14-qism:
asyncio.TaskGroup—ExceptionGroup concurrent.futures: parallel ishlarpydantic,marshmallow: validatsiya xatolarini yig'ish- PEP 654: Exception Groups and
except* - PEP 3151: OS xatolari ierarxiyasini qayta qurish
8. Eng yaxshi amaliyotlar
Aniqdan umumiyga. Avlod turi avval yozilsin.
Guruh turlarini biling.
LookupError,OSError,ArithmeticError.Toifalarni o'zgaruvchiga chiqaring.
VAQTINCHALIK = (...).Har toifaga o'z strategiyasi. Qayta urinish, HTTP kodi, jurnal darajasi.
Validatsiyada barcha xatolarni yig'ing. Foydalanuvchi bir marta ko'rsin.
ExceptionGroup— parallel ishlar uchun. 3.11+.Xato yo'lini (path) ko'rsating.
xodim[2].manzil.shahar.Linter ishlating.
ruff B014o'likexceptbloklarini topadi.
9. Amaliy topshiriq
Vazifa 1: Qaysi blok ishlaydi?
try:
raise X()
except KeyError: print(1)
except LookupError: print(2)
except (ValueError, TypeError): print(3)
except OSError: print(4)
except Exception: print(5)X = ?
1. KeyError
2. IndexError
3. ValueError
4. UnicodeDecodeError
5. FileNotFoundError
6. ConnectionResetError
7. TimeoutError
8. ZeroDivisionError
9. json.JSONDecodeError
10. RecursionError
11. ModuleNotFoundError
12. KeyboardInterruptJavoblar
1—KeyError2—LookupError33—ValueErroravlodi4—OSErroravlodi4—ConnectionError→OSError4—TimeoutErrorhamOSError5—ArithmeticError→Exception3—ValueErroravlodi5—RuntimeError→Exception5—ImportError→Exception- Ushlanmaydi —
BaseException
Vazifa 2: Xatolarni tuzating
1. except ValueError: ...
except json.JSONDecodeError: ...
2. except ValueError, TypeError: ...
3. except Exception: ...
except ValueError: ...
4. except OSError: ...
except TimeoutError: ...
5. except* ValueError: ...
except TypeError: ...
6. raise ExceptionGroup("x", [])
7. for x in m: tekshir(x) # barcha xatolar kerak
8. except (ConnectionError, OSError): ...Javoblar
1. JSONDecodeError ni AVVAL
2. except (ValueError, TypeError):
3. ValueError ni AVVAL
4. TimeoutError ni AVVAL (OSError avlodi)
5. Ikkalasini ham except* qiling
6. Bo'sh guruh mumkin emas — shart qo'ying
7. Xatolarni yig'ing (Yiguvchi yoki ro'yxat)
8. OSError yetadi (ConnectionError uning avlodi)Vazifa 3: Xato toifalovchi
Yozing:
Toifaenum: vaqtinchalik, ma'lumot, ruxsat, resurs, dastur- Tur → toifa xaritasi (tartib bilan)
- Har toifa uchun strategiya (qayta urinish, HTTP, jurnal)
- O'lik kod tekshiruvi
- Qamrab olinmagan turlarni topish
- Statistika va hisobot
Vazifa 4: except tartibi tekshiruvchisi
Vosita yozing (AST bilan):
- Har
trydagiexceptturlarini olsin - O'lik bloklarni topsin (
issubclass) - Tuple ichidagi ortiqcha turlarni
except:vaexcept Exception:larni- Tuzatilgan tartibni taklif qilsin
ruff B014bilan solishtiring
Vazifa 5: ExceptionGroup yig'uvchi
- Kontekst menejeri:
with yigish() as y: y.ushla()— bitta amal xatosini yig'sin- Ichma-ich yig'uvchilar (yo'l bilan)
- Chegara va qat'iy rejim
except*bilan toifalash- Python 3.10 uchun zaxira variant
Vazifa 6: Parallel ishlar
ThreadPoolExecutorbilan N ish- Barcha xatolarni yig'sin
ExceptionGroupbilan ko'tarsinexcept*bilan toifalarga ajratsin- Qayta urinish faqat vaqtinchalik xatolarda
- Statistika: muvaffaqiyat/xato/qayta urinish
Vazifa 7: O'ylash
Nega Python ExceptionGroup ni faqat 3.11 da qo'shdi — bu ehtiyoj ancha oldin bo'lgan-ku?
Javob
Chunki asyncio.TaskGroup uni majburiy qildi — undan oldin muammo "chetlab o'tiladigan" edi.
1. Muammo ancha oldin ma'lum edi
# 2010-yillar: har kutubxona o'z yechimini yasadi
# concurrent.futures
for k in futures:
try:
k.result()
except Exception as e:
xatolar.append(e) # ⚠️ qo'lda
# multiprocessing
hovuz.map(f, malumot) # ⚠️ birinchi xato
# pytest
class ExceptionInfo: ... # ⚠️ o'z tuzilmasi
# trio (2017)
class MultiError(BaseException): # ⭐ ExceptionGroup ning bobosi
def __init__(self, exceptions): ... Trio kutubxonasi (Nathaniel Smith, 2017) MultiError ni yaratdi — bu ExceptionGroup ning to'g'ridan-to'g'ri ilhomlantiruvchisi.
2. Nega bunchalik kech
a) Sintaksis o'zgarishi kerak edi
except* ValueError as eg: # ⭐ YANGI kalit so'zPython juda kamdan-kam yangi sintaksis qo'shadi. Oxirgi 10 yilda:
| Versiya | Yangi sintaksis |
|---|---|
| 3.5 | async/await, @ (matmul) |
| 3.6 | f-string, := yo'q hali |
| 3.8 | := (walrus), / (pozitsion) |
| 3.10 | match/case |
| 3.11 | except* |
| 3.12 | tur parametrlari def f[T]() |
Har biri yillar muhokama qilinadi.
b) Semantika murakkab
Savollar, javob talab qilgan:
# 1. Bitta istisno ham guruh bo'ladimi?
try:
raise ValueError()
except* ValueError as eg:
type(eg) # ExceptionGroup ⭐ ha
# 2. Ichma-ich guruhlar qanday?
ExceptionGroup("a", [ExceptionGroup("b", [ValueError()])])
# → except* ValueError uni topadimi? ⭐ ha, avtomatik yassilanadi
# 3. Traceback qanday ko'rsatiladi?
# → daraxt shaklida ⭐
# 4. Bir necha blok ishlagach nima bo'ladi?
# → ushlanmaganlar guruhda uzatiladi ⭐
# 5. except va except* aralashsa?
# → ❌ SyntaxError
# 6. break/continue/return except* da?
# → ❌ SyntaxError (murakkab semantika)Har savolga javob o'ylab topilishi kerak edi.
c) Orqaga moslik
# Mavjud kod buzilmasligi kerak:
try:
ish()
except Exception: # ⚠️ ExceptionGroup ni ushlaydimi?
... Yechim: ExceptionGroup — Exception avlodi. Ya'ni eski kod uni ushlaydi, lekin ichidagilarni ajrata olmaydi.
3. Nima majburladi: asyncio.TaskGroup
Python 3.11 da asyncio.TaskGroup qo'shildi (trio dan ilhom):
async with asyncio.TaskGroup() as tg:
tg.create_task(ish1())
tg.create_task(ish2())
tg.create_task(ish3())Savol: uchtasi ham xato bersa — nima ko'tariladi?
Variantlar:
| Variant | Muammo |
|---|---|
| Birinchisi | Qolgan ikkitasi yo'qoladi |
| Ro'yxat | raise ro'yxatni qabul qilmaydi |
| Maxsus istisno | except bilan ajratib bo'lmaydi |
ExceptionGroup |
To'g'ri yechim |
Ya'ni TaskGroup ExceptionGroup siz mumkin emas edi.
4. PEP 654 tarixi
| Sana | Voqea |
|---|---|
| 2017 | Trio MultiError ni yaratadi |
| 2019 | Trio MultiError v2 muhokamasi |
| 2021-02 | PEP 654 taklif qilinadi (Irit Katriel, Yury Selivanov, Guido) |
| 2021-09 | PEP qabul qilinadi |
| 2022-10 | Python 3.11 chiqadi |
Taklif → chiqish: 20 oy. Muhokama esa 4 yil.
5. Nima uchun MultiError emas
Trio dagi MultiError muammolari:
# ⚠️ 1. except bilan ajratib bo'lmaydi
try:
ish()
except MultiError as me:
for e in me.exceptions: # ⚠️ qo'lda
if isinstance(e, ValueError):
...
# ⚠️ 2. Ichma-ich guruhlar qo'lda yassilanadi
# ⚠️ 3. Traceback chalkash
# ⚠️ 4. Standart emas — har kutubxona o'ziniki except* — til darajasidagi yechim:
except* ValueError as eg: # ✅ avtomatik6. Boshqa tillar
| Til | Ko'p istisno |
|---|---|
| Python 3.11+ | ExceptionGroup + except* |
| Java | Throwable.addSuppressed() |
| C# | AggregateException |
| JavaScript | AggregateError (ES2021) |
| Go | errors.Join() (1.20, 2023) |
| Rust | Qo'lda (Vec<Error>) |
C# — eng yaqin:
try {
Task.WaitAll(tasks);
} catch (AggregateException ae) {
ae.Handle(e => { // ⚠️ qo'lda filtrlash
if (e is ArgumentException) return true;
return false;
});
} C# da catch* yo'q — filtrlash qo'lda.
Go 1.20 (2023):
err := errors.Join(err1, err2, err3)
errors.Is(err, target) // ⭐ ichidagilarni tekshiradiPython dan 8 yil keyin, lekin except* kabi sintaksis yo'q.
7. Amalda kim ishlatadi
# 1. asyncio.TaskGroup (3.11+)
async with asyncio.TaskGroup() as tg: ...
# 2. Validatsiya kutubxonalari
# pydantic v2 hali ExceptionGroup ishlatmaydi (orqaga moslik)
# 3. Test frameworklari
# pytest — muhokama qilinmoqda
# 4. Ma'lumot quvurlari
raise ExceptionGroup("Yuklashda xatolar", xatolar)
# 5. Parallel so'rovlarSekin qabul qilinmoqda, chunki:
- 3.11+ talab qiladi (2022)
- Ko'p loyihalar 3.9/3.10 da
- Kutubxonalar orqaga moslikni saqlaydi
8. Zaxira variant (3.10 va oldin)
try:
from builtins import ExceptionGroup
except ImportError:
# ⭐ exceptiongroup kutubxonasi
from exceptiongroup import ExceptionGroup exceptiongroup — PyPI paketi, except* ni ham taqlid qiladi (catch() kontekst menejeri bilan).
9. Nima o'rgandik
Python ExceptionGroup ni kech qo'shdi, chunki:
- Yangi sintaksis (
except*) — Python juda ehtiyotkor - Semantika murakkab — 6+ savol javob talab qilgan
- Orqaga moslik — mavjud kod buzilmasligi kerak
- "Chetlab o'tish" mumkin edi — har kutubxona o'ziniki yasagan
-
asyncio.TaskGroupmajburladi — usiz mumkin emas edi
Umumiy naqsh: Python yangi xususiyatni haqiqiy ehtiyoj paydo bo'lgandagina qo'shadi:
| Xususiyat | Nima majburladi |
|---|---|
async/await |
Tarmoq dasturlari |
dataclass |
attrs ning muvaffaqiyati |
match/case |
Strukturaviy ma'lumot |
except* |
asyncio.TaskGroup |
:= |
Comprehension da takroriy hisoblash |
Va har biri yillar muhokama qilinadi — bu Pythonning barqarorligi sababi.
Nimani mustahkamlaydi: 2.5, 2.6-bo'limlar.
Xulosa
Bu darsda bir nechta istisno bilan ishlashni o'rgandik.
Eng muhim uch fikr:
exceptbloklari tartib bilan tekshiriladi va faqat bittasi ishlaydi. Avlod turi ota-sinfdan avval yozilishi kerak — aks holda u o'lik kod bo'ladi. Bu ayniqsaJSONDecodeError/ValueError,TimeoutError/OSError,KeyError/LookupErrorjuftliklarida uchraydi.Ierarxiyani biling va undan foydalaning.
LookupError—KeyErrorvaIndexError;OSError— barcha fayl va tarmoq xatolari;ConnectionError— to'rtta ulanish xatosi. Amaliy strategiya — xatolarni toifalarga ajratish (vaqtinchalik / ma'lumot / ruxsat / resurs / dastur) va har toifaga o'z ish tartibini berish: qayta urinish, HTTP kodi, jurnal darajasi.ExceptionGroupvaexcept*(3.11+) — bir vaqtda bir nechta xato uchun.except*da, oddiyexceptdan farqli, bir nechta blok ishlashi mumkin va har biri o'z turidagi istisnolarni oladi. Bu parallel ishlar (asyncio.TaskGroup) va validatsiya uchun juda muhim: foydalanuvchi barcha muammoni bir marta ko'radi, birinchisini tuzatib qayta yuborishga majbur bo'lmaydi.
Keyingi darsda raise ni chuqur ko'ramiz: istisno ko'tarish, qayta ko'tarish, from bilan zanjirlash va istisnolarni to'g'ri o'rash.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!