IlmHamroh
Python kursi/Xatolar2/8-dars38 daqiqa
Mundarija (21)

9.2-dars: try / except

9-QISM — XATOLAR VA ISTISNOLAR · 2-dars


1. Kirish va motivatsiya

Bu kod "xavfsiz" ko'rinadi:

python
try:
    natija = hisobla(malumot)
except:                             # ⚠️
    natija = None

Aslida u falokat:

python
try:
    natija = hisobla(malumot)
except:
    natija = None
  • Ctrl+C ishlamaydi (KeyboardInterrupt ushlanadi)
  • SystemExit to'siladi — dastur to'xtamaydi
  • MemoryError yashiriladi
  • Sizning typoingiz (NameError) ham jimgina yutiladi
  • Xato sababi butunlay yo'qoladi

To'g'ri variant:

python
try:
    natija = hisobla(malumot)
except (ValueError, KeyError) as e:         # ⭐ ANIQ turlar
    logging.warning("Hisoblab bo'lmadi: %s", e)
    natija = None

Bu darsda:

  • try/except mexanizmi va bajarilish tartibi
  • Yalang'och except: — nega taqiqlangan
  • Qaysi turni ushlash: aniqlikdan umumiylikka
  • as e va istisno obyekti
  • EAFP vs LBYL — Pythoncha uslub
  • Ichma-ich try va qayta ko'tarish

2. Nazariya — chuqur tushuntirish

2.1. Asosiy sintaksis

python
try:
    xavfli_amal()                   # ⭐ himoyalangan blok
except ValueError as e:             # ⭐ tur + obyekt
    ishlov(e)

Bajarilish tartibi:

1. try bloki boshlanadi
2. Istisno bo'lmasa → except o'tkazib yuboriladi
3. Istisno bo'lsa:
   a. try ning QOLGAN qismi BAJARILMAYDI
   b. except turlari TARTIB BILAN tekshiriladi
   c. Birinchi mos keladigan bajariladi
   d. Hech biri mos kelmasa → yuqoriga uzatiladi
python
try:
    print("1")
    1 / 0
    print("2")                      # ⚠️ BAJARILMAYDI
except ZeroDivisionError:
    print("3")
print("4")
# → 1, 3, 4

2.2. Yalang'och except:

python
try:
    ...
except:                             # ❌ HECH QACHON
    ...

except: — except BaseException: bilan bir xil.

Ierarxiya:

BaseException                       ⚠️ except: shuni ushlaydi
 ├── SystemExit                     sys.exit()
 ├── KeyboardInterrupt              Ctrl+C
 ├── GeneratorExit                  generator yopilishi
 └── Exception                      ⭐ ODATIY xatolar
      ├── ValueError
      ├── TypeError
      └── ... (barcha qolgani)

Nima buziladi:

python
while True:
    try:
        ish()
    except:                         # ⚠️ Ctrl+C ishlamaydi
        continue                    # cheksiz tsikl!
python
try:
    sys.exit(1)                     # ⚠️ dastur to'xtamaydi
except:
    print("nima bo'ldi?")
python
try:
    natija = hisoblaa(x)            # ⚠️ typo: NameError
except:
    natija = 0                      # ⚠️ jimgina yashirildi

To'g'ri variantlar:

python
except Exception as e:              # ⚠️ hali ham keng, lekin xavfsizroq
except (ValueError, KeyError) as e: # ✅ aniq
except ValueError as e:             # ✅ eng aniq

Qoida: except Exception: — faqat eng yuqori darajada (main(), veb ishlovchi), va doim jurnalga yozing.

2.3. Tur tanlash

Aniqlikdan umumiylikka:

python
try:
    m = json.loads(matn)
    q = m["kalit"]
    n = int(q)
except json.JSONDecodeError:        # ⭐ eng aniq
    ...
except KeyError:
    ...
except ValueError:                  # ⚠️ JSONDecodeError ham ValueError!
    ...

Tartib muhim — birinchi mos keladigani ishlaydi:

python
except ValueError: ...              # ⚠️ birinchi
except json.JSONDecodeError: ...    # ❌ HECH QACHON ishlamaydi

JSONDecodeError — ValueError avlodi, shuning uchun avval yozilishi kerak.

Bir nechta tur:

python
except (ValueError, TypeError) as e:            # ⭐ tuple
except (ValueError, TypeError, KeyError):

Guruh ushlash:

python
except LookupError:                 # KeyError + IndexError
except ArithmeticError:             # ZeroDivisionError, OverflowError
except OSError:                     # barcha fayl/tarmoq

2.4. as e — istisno obyekti

python
except ValueError as e:
    print(type(e))                  # <class 'ValueError'>
    print(str(e))                   # xabar
    print(e.args)                   # (xabar,) — tuple
    print(repr(e))                  # ValueError('xabar')
    print(e.__traceback__)          # traceback obyekti

e blok tugagach o'chiriladi:

python
try:
    1 / 0
except ZeroDivisionError as e:
    pass
print(e)                            # ❌ NameError

Python 3 da except ... as e: blok oxirida del e qiladi — aylanma havolani oldini olish uchun.

Saqlash kerak bo'lsa:

python
xato = None
try:
    ...
except ValueError as e:
    xato = e                        # ⭐ boshqa nomga

Maxsus atributlar:

python
except OSError as e:
    e.errno                         # xato raqami
    e.strerror                      # tizim xabari
    e.filename                      # fayl nomi

except UnicodeDecodeError as e:
    e.encoding, e.object, e.start, e.end, e.reason

except subprocess.CalledProcessError as e:
    e.returncode, e.output, e.stderr

2.5. EAFP vs LBYL

LBYL — "Look Before You Leap":

python
if os.path.exists(yol):             # ⚠️ tekshiruv
    with open(yol) as f:            # ⚠️ shu orada fayl o'chishi mumkin
        ...

EAFP — "Easier to Ask Forgiveness than Permission":

python
try:
    with open(yol) as f:            # ✅ atomik
        ...
except FileNotFoundError:
    ...

Uch sabab EAFP foydasiga:

  1. Poyga holati yo'q — tekshiruv va amal orasida holat o'zgarmaydi
  2. Tezroq — istisno kamdan-kam bo'lsa (try deyarli bepul)
  3. Qisqaroq — bitta tekshiruv o'rniga

LBYL qachon yaxshi:

python
# 1. Istisno TEZ-TEZ bo'lsa
if k in d:                          # ✅ 50% hollarda yo'q bo'lsa
    ...

# 2. Bir necha shart
if x and y and z.mavjud:            # ✅ o'qiladigan

# 3. Yon ta'sirni oldini olish
if hajm_yetarlimi():                # ✅ yozishdan oldin
    yoz(katta_malumot)

Tezlik solishtiruvi:

Python 3.14, lug'atdan o'qish (bitta amal):

                    try/except      if + []
Kalit BOR           ~87 ns          ~131 ns     ⭐ EAFP ~1.5× TEZ
Kalit YO'Q          ~336 ns         ~87 ns      ⚠️ EAFP ~4× sekin

Kalit bor bo'lsa EAFP hatto tezroq — LBYL da kalit ikki marta qidiriladi (in va []), EAFP da bir marta. Python 3.11+ da try blokiga kirish deyarli bepul ("zero-cost"), qimmat narsa — istisnoni ko'tarish va ushlash.

Ya'ni: xato kamdan-kam bo'lsa — EAFP; tez-tez bo'lsa — LBYL.

2.6. Ichma-ich va qayta ko'tarish

python
try:
    try:
        xavfli()
    except ValueError:
        tuzat()                     # ichki
        raise                       # ⭐ QAYTA ko'tarish
except ValueError as e:
    logging.error("Tuzatib bo'lmadi: %s", e)

raise (argumentsiz) — asl traceback saqlanadi:

python
except ValueError:
    tozala()
    raise                           # ✅ asl traceback

except ValueError as e:
    raise e                         # ⚠️ ishlaydi, lekin ortiqcha traceback yozuvi

"raise e traceback'ni yo'qotadi" degan gap Python 2 dan qolgan. Python 3 da asl iz saqlanadi, faqat raise e qatori uchun qo'shimcha yozuv paydo bo'ladi (batafsil — 9.5-dars).

Shartli ushlash:

python
except OSError as e:
    if e.errno != errno.ENOENT:
        raise                       # ⭐ boshqasini uzatamiz
    # faqat "fayl yo'q" ni ishlaymiz

2.7. Antipatternlar

python
# ❌ 1. Yalang'och except
except: ...

# ❌ 2. Jimgina yutish
except Exception:
    pass                            # ⚠️ xato yo'qoldi

# ❌ 3. print bilan
except Exception as e:
    print(f"Xato: {e}")             # ⚠️ traceback yo'q, jurnal yo'q

# ❌ 4. Juda keng try
try:
    a = f()
    b = g()
    c = h()                         # ⚠️ qaysi biri buzildi?
except Exception:
    ...

# ❌ 5. Nazorat oqimi sifatida
try:
    return d[k]
except KeyError:
    return sukut                    # ⚠️ d.get(k, sukut) yaxshiroq
                                    # (agar tez-tez bo'lsa)

# ❌ 6. Xatoni o'zgartirmasdan qayta ko'tarish
except ValueError as e:
    raise e                         # ⚠️ raise yetadi

3. Tez ma'lumotnoma

Sintaksis

python
try:
    xavfli()
except ValueError as e:         aniq tur
except (TypeError, KeyError):   bir nechta
except Exception as e:          ⚠️ faqat yuqori darajada
except:                         ❌ HECH QACHON

Yalang'och except

except:  ≡  except BaseException:

Ushlaydi:
  KeyboardInterrupt   ⚠️ Ctrl+C ishlamaydi
  SystemExit          ⚠️ sys.exit() to'siladi
  GeneratorExit       ⚠️
  + barcha typo lar

Tartib

python
except JSONDecodeError:     ⭐ AVLOD avval
except ValueError:          keyin ota-sinf

⚠️ Teskari bo'lsa — avlod HECH QACHON ishlamaydi

EAFP vs LBYL

EAFP (try/except)   xato KAMDAN-KAM bo'lsa    ⭐ Pythoncha
LBYL (if)           xato TEZ-TEZ bo'lsa

Istisno bo'lmasa: try tezroq yoki teng (qidiruv bir marta)
Istisno bo'lsa:   try ~4× sekinroq (ko'tarish qimmat)

Qayta ko'tarish

python
raise                       ✅ asl traceback, toza
raise e                     ⚠️ asl traceback + ortiqcha yozuv
raise X("...") from e       ✅ o'rash

4. Batafsil misollar

Misol 1 — Mexanizm va tartib

python
"""try/except qanday ishlaydi."""

import json
import sys
import traceback

print("=== 1. Bajarilish tartibi ===\n")


def kuzatuv(xatoli: bool):
    izlar = []
    try:
        izlar.append("try boshi")
        if xatoli:
            1 / 0
        izlar.append("try oxiri")           # ⚠️ xato bo'lsa bajarilmaydi
    except ZeroDivisionError:
        izlar.append("except")
    izlar.append("keyin")
    return izlar


print(f"  Xatosiz: {kuzatuv(False)}")
print(f"  Xato:    {kuzatuv(True)}")

print(f"""
  ⭐ TARTIB:
     1. try bloki boshlanadi
     2. Xato bo'lsa → try ning QOLGAN qismi BAJARILMAYDI
     3. except turlari TARTIB bilan tekshiriladi
     4. Birinchi MOS keladigani bajariladi
     5. Hech biri mos kelmasa → yuqoriga uzatiladi
""")


print("=== ⭐ 2. Tur tanlash tartibi ===\n")


def tahlil(matn: str, tartib: str = "togri"):
    """JSON tahlil qilish — turli except tartibi bilan."""
    if tartib == "togri":
        try:
            return ("✅", json.loads(matn))
        except json.JSONDecodeError as e:            # ⭐ AVLOD avval
            return ("JSONDecodeError", str(e)[:30])
        except ValueError as e:
            return ("ValueError", str(e)[:30])
    else:
        try:
            return ("✅", json.loads(matn))
        except ValueError as e:                      # ⚠️ OTA-SINF avval
            return ("ValueError", str(e)[:30])
        except json.JSONDecodeError as e:            # ❌ hech qachon
            return ("JSONDecodeError", str(e)[:30])


MATNLAR = ['{"a": 1}', "{buzilgan}", "[1, 2]", "not json"]

print(f"  {'Kirish':<16} {'To`g`ri tartib':<24} {'Noto`g`ri tartib'}")
print("  " + "─" * 66)
for m in MATNLAR:
    t1 = tahlil(m, "togri")
    t2 = tahlil(m, "notogri")
    print(f"  {m:<16} {t1[0]:<24} {t2[0]}")

print(f"""
  ⭐ JSONDecodeError.__mro__:
     {[c.__name__ for c in json.JSONDecodeError.__mro__[:4]]}

  ⚠️ ValueError avval yozilsa — JSONDecodeError bloki
     HECH QACHON ishlamaydi (o'lik kod).

  ✅ QOIDA: ANIQDAN UMUMIYGA
""")


print("=== ⚠️ 3. Yalang'och except ===\n")

print(f"  BaseException ierarxiyasi:\n")
IERARXIYA = [
    (BaseException, 0),
    (SystemExit, 1),
    (KeyboardInterrupt, 1),
    (GeneratorExit, 1),
    (Exception, 1),
    (ValueError, 2),
    (TypeError, 2),
    (LookupError, 2),
    (KeyError, 3),
    (IndexError, 3),
]
for X, daraja in IERARXIYA:
    belgi = "⚠️" if daraja == 1 and X is not Exception else "  "
    print(f"    {'  ' * daraja}{'└── ' if daraja else ''}"
          f"{X.__name__:<22} {belgi}")

print(f"\n  ⚠️ except: — BaseException ni ushlaydi\n")


def yalangoch_test(istisno):
    """Yalang'och except nima ushlaydi."""
    try:
        raise istisno
    except:
        return "ushlandi"


def exception_test(istisno):
    try:
        raise istisno
    except Exception:
        return "ushlandi"
    except BaseException:
        return "o'tdi"


ISTISNOLAR = [
    ValueError("test"),
    KeyError("test"),
    KeyboardInterrupt(),
    SystemExit(1),
    GeneratorExit(),
    MemoryError(),
]

print(f"  {'Istisno':<24} {'except:':<16} {'except Exception:'}")
print("  " + "─" * 60)
for e in ISTISNOLAR:
    try:
        r1 = yalangoch_test(e)
    except BaseException:
        r1 = "o'tdi"
    try:
        r2 = exception_test(e)
    except BaseException:
        r2 = "✅ o'tdi"
    belgi = "⚠️" if r1 == "ushlandi" and r2 != "ushlandi" else ""
    print(f"  {type(e).__name__:<24} {r1:<16} {r2} {belgi}")

print(f"""
  ⚠️ HAQIQIY MUAMMOLAR:

     1. Ctrl+C ishlamaydi:
        while True:
            try: ish()
            except: continue        ⚠️ cheksiz tsikl

     2. sys.exit() to'siladi:
        try: sys.exit(1)
        except: pass                ⚠️ dastur to'xtamaydi

     3. Typo yashiriladi:
        try: natija = hisoblaa(x)   ⚠️ NameError
        except: natija = 0          ⚠️ jimgina

     4. MemoryError yashiriladi:
        ⚠️ Xotira tugagan, lekin dastur davom etadi
""")


print("=== 4. Typo ni yashirish ===\n")


def yomon(m):
    try:
        return sum(m) / lenn(m)                 # ⚠️ typo: lenn
    except:
        return 0


def yaxshi(m):
    try:
        return sum(m) / lenn(m)                 # ⚠️ typo
    except (TypeError, ZeroDivisionError):
        return 0


print(f"  yomon([1, 2, 3])  = {yomon([1, 2, 3])}   "
      f"⚠️ 0 — lekin typo bor!")
try:
    yaxshi([1, 2, 3])
except NameError as e:
    print(f"  yaxshi([1, 2, 3]) → ✅ NameError: {e}")

print(f"""
  ⭐ ANIQ turlar typo larni OCHIB BERADI.
     Yalang'och except — ularni YASHIRADI.
""")


print("=== 5. as e va istisno obyekti ===\n")


def xato_tahlili(f, nom: str):
    try:
        f()
    except Exception as e:
        print(f"  {nom}:")
        print(f"    type(e)   = {type(e).__name__}")
        print(f"    str(e)    = {str(e)!r}")
        print(f"    repr(e)   = {repr(e)}")
        print(f"    e.args    = {e.args}")
        maxsus = [a for a in dir(e)
                  if not a.startswith("_") and a != "args"
                  and a not in ("with_traceback", "add_note")]
        if maxsus:
            print(f"    maxsus    = {maxsus}")
            for a in maxsus[:3]:
                try:
                    print(f"      e.{a:<12} = {getattr(e, a)!r}")
                except Exception:
                    pass
        print()


xato_tahlili(lambda: 1 / 0, "ZeroDivisionError")
xato_tahlili(lambda: {"a": 1}["b"], "KeyError")
xato_tahlili(lambda: open("mavjud_emas_9999.txt"), "FileNotFoundError")
xato_tahlili(lambda: "O'zbek".encode("ascii"), "UnicodeEncodeError")

print(f"  ⚠️ e blok TASHQARISIDA yo'q:\n")
try:
    1 / 0
except ZeroDivisionError as e:
    ichkarida = str(e)
try:
    print(e)
except NameError as err:
    print(f"    print(e) → ✅ NameError: {err}")

print(f"    Ichkarida: {ichkarida!r}")

print(f"""
  ⭐ SABAB: Python 3 da except bloki oxirida
     avtomatik `del e` bajariladi.

     Sabab — aylanma havola:
       e → __traceback__ → ramka → lokal → e

  ✅ Saqlash kerak bo'lsa:
     xato = None
     try: ...
     except ValueError as e:
         xato = e                   ⭐ boshqa nomga
""")


print("=== ⭐ 6. add_note (3.11+) ===\n")

try:
    try:
        1 / 0
    except ZeroDivisionError as e:
        e.add_note("Kontekst: hisobot yasashda")        # ⭐ 3.11+
        e.add_note("Foydalanuvchi: aziz@wisar.uz")
        raise
except ZeroDivisionError as e:
    print(f"  Izohlar: {e.__notes__}")
    print(f"\n  Traceback da:")
    for q in traceback.format_exc().rstrip().split("\n"):
        print(f"    {q}")

print(f"""
  ⭐ add_note() — istisnoni O'ZGARTIRMASDAN kontekst qo'shadi.
     Traceback da avtomatik ko'rinadi.

  ⚠️ Python 3.11+ (PEP 678)
""")

Natijaning muhim qismi:

text
=== 1. Bajarilish tartibi ===

  Xatosiz: ['try boshi', 'try oxiri', 'keyin']
  Xato:    ['try boshi', 'except', 'keyin']

=== ⭐ 2. Tur tanlash tartibi ===

  Kirish           To`g`ri tartib           Noto`g`ri tartib
  ──────────────────────────────────────────────────────────────────
  {"a": 1}         ✅                        ✅
  {buzilgan}       JSONDecodeError           ValueError
  not json         JSONDecodeError           ValueError

=== ⚠️ 3. Yalang'och except ===

  Istisno                  except:          except Exception:
  ────────────────────────────────────────────────────────────
  ValueError               ushlandi         ushlandi
  KeyboardInterrupt        ushlandi         o'tdi ⚠️
  SystemExit               ushlandi         o'tdi ⚠️

=== 4. Typo ni yashirish ===

  yomon([1, 2, 3])  = 0   ⚠️ 0 — lekin typo bor!
  yaxshi([1, 2, 3]) → ✅ NameError: name 'lenn' is not defined

Nima ko'rsatdi: 2.1, 2.2, 2.3, 2.4-bo'limlar.

Misol 2 — EAFP vs LBYL

python
"""Ikki uslub: qachon qaysi biri."""

from __future__ import annotations

import os
import time
import timeit
from pathlib import Path

print("=== ⭐ 1. Poyga holati ===\n")

print("""  ⚠️ LBYL — poyga holati (race condition):

     if os.path.exists(yol):        # 1. tekshiruv
         # ⚠️ SHU YERDA boshqa jarayon faylni O'CHIRISHI mumkin
         with open(yol) as f:       # 2. ochish
             ...                    # ❌ FileNotFoundError

  ✅ EAFP — atomik:

     try:
         with open(yol) as f:       # ⭐ bitta amal
             ...
     except FileNotFoundError:
         ...

  ⭐ Boshqa poyga holatlari:
     • Fayl ruxsatlari o'zgaradi
     • Lug'at boshqa ipchada o'zgaradi
     • Tarmoq ulanishi uziladi
     • Disk to'ladi
""")


print("=== 2. Tezlik solishtiruvi ===\n")

LUGAT = {f"kalit{i}": i for i in range(1000)}
N = 500_000


def lbyl_bor(d, k):
    if k in d:
        return d[k]
    return None


def eafp_bor(d, k):
    try:
        return d[k]
    except KeyError:
        return None


print(f"  {N:,} chaqiruv:\n")
print(f"  {'Holat':<24} {'LBYL':>10} {'EAFP':>10} {'Farq'}")
print("  " + "─" * 56)

HOLATLAR = [
    ("Kalit BOR (100%)",    "kalit500"),
    ("Kalit YO'Q (100%)",   "mavjud_emas"),
]

for nom, k in HOLATLAR:
    t1 = timeit.timeit(lambda: lbyl_bor(LUGAT, k), number=N)
    t2 = timeit.timeit(lambda: eafp_bor(LUGAT, k), number=N)
    farq = f"{t2/t1:.1f}× sekin" if t2 > t1 else f"{t1/t2:.1f}× tez"
    print(f"  {nom:<24} {t1:>8.3f}s {t2:>9.3f}s  EAFP {farq}")

# Aralash holat
import random
random.seed(42)
KALITLAR = ([f"kalit{i}" for i in range(950)]
            + [f"yoq{i}" for i in range(50)])
random.shuffle(KALITLAR)


def lbyl_aralash():
    for k in KALITLAR:
        lbyl_bor(LUGAT, k)


def eafp_aralash():
    for k in KALITLAR:
        eafp_bor(LUGAT, k)


t1 = timeit.timeit(lbyl_aralash, number=500)
t2 = timeit.timeit(eafp_aralash, number=500)
print(f"  {'5% xato (aralash)':<24} {t1:>8.3f}s {t2:>9.3f}s  "
      f"EAFP {t2/t1:.2f}×")

KALITLAR2 = ([f"kalit{i}" for i in range(500)]
             + [f"yoq{i}" for i in range(500)])
random.shuffle(KALITLAR2)


def lbyl2():
    for k in KALITLAR2: lbyl_bor(LUGAT, k)


def eafp2():
    for k in KALITLAR2: eafp_bor(LUGAT, k)


t1 = timeit.timeit(lbyl2, number=500)
t2 = timeit.timeit(eafp2, number=500)
print(f"  {'50% xato':<24} {t1:>8.3f}s {t2:>9.3f}s  "
      f"EAFP {t2/t1:.2f}×")

print(f"""
  ⭐ XULOSA:

     Xato YO'Q          → try/except deyarli BEPUL (hatto tezroq)
     Xato BOR           → try/except bir necha marta sekinroq
     5% xato            → farq kichik
     50% xato           → LBYL sezilarli tezroq

  ⭐ QOIDA: istisno ISTISNO bo'lsin (kamdan-kam).
""")


print("=== 3. Amaliy holatlar ===\n")

print("""  ✅ EAFP TO'G'RI:

     # 1. Fayl bilan ishlash (poyga holati)
     try:
         with open(yol) as f: ...
     except FileNotFoundError: ...

     # 2. Tur o'girish
     try:
         n = int(matn)
     except ValueError:
         n = 0

     # 3. Atribut (duck typing)
     try:
         return obj.metod()
     except AttributeError:
         return sukut

     # 4. Tarmoq
     try:
         javob = sorov(url)
     except ConnectionError: ...

     # 5. Import (ixtiyoriy bog'liqlik)
     try:
         import ujson as json
     except ImportError:
         import json


  ✅ LBYL TO'G'RI:

     # 1. Xato TEZ-TEZ
     if k in d: ...                 # 50% hollarda yo'q

     # 2. Bir necha shart
     if x and y and z > 0: ...

     # 3. Yon ta'sirni oldini olish
     if bosh_joy() > kerak:
         yoz(katta_malumot)         # ⚠️ yozib, keyin xato — yomon

     # 4. Oddiy tekshiruv
     if lst: ...                    # try/except ortiqcha
""")


print("=== ⭐ 4. Tayyor muqobillar ===\n")

d = {"a": 1}
lst = [1, 2, 3]
s = {1, 2}

MUQOBILLAR = [
    ("d[k]",                "d.get(k, sukut)",
     lambda: d.get("yoq", "sukut")),
    ("d.pop(k)",            "d.pop(k, sukut)",
     lambda: d.pop("yoq", "sukut")),
    ("s.remove(x)",         "s.discard(x)",
     lambda: s.discard(99)),
    ("next(it)",            "next(it, sukut)",
     lambda: next(iter([]), "sukut")),
    ("lst[i]",              "lst[i:i+1]",
     lambda: lst[99:100]),
    ("int(x)",              "⚠️ muqobil yo'q — try kerak", None),
    ("getattr(o, n)",       "getattr(o, n, sukut)",
     lambda: getattr(d, "yoq", "sukut")),
    ("os.remove(p)",        "Path(p).unlink(missing_ok=True)", None),
    ("os.mkdir(p)",         "Path(p).mkdir(exist_ok=True)", None),
    ("d[k] += 1",           "defaultdict / Counter", None),
]

print(f"  {'Xatoli':<22} {'Xavfsiz muqobil':<38} {'Natija'}")
print("  " + "─" * 74)
for xatoli, xavfsiz, f in MUQOBILLAR:
    natija = repr(f()) if f else "—"
    print(f"  {xatoli:<22} {xavfsiz:<38} {natija}")

print(f"""
  ⭐ MUQOBIL BO'LSA — UNI ISHLATING:
     d.get(k, sukut)     ✅ oddiyroq va tezroq
     try: d[k]           ⚠️ ortiqcha

  ⚠️ LEKIN: agar YO'Q bo'lish HAQIQATAN xato bo'lsa —
     try/except aniqroq niyatni bildiradi.
""")


print("=== 5. Aralash yondashuv ===\n")


def sozlama_oqi_lbyl(yol: str) -> dict:
    """⚠️ Ko'p tekshiruv."""
    import json
    if not os.path.exists(yol):
        return {}
    if not os.path.isfile(yol):
        return {}
    if not os.access(yol, os.R_OK):
        return {}
    if os.path.getsize(yol) == 0:
        return {}
    with open(yol, encoding="utf-8") as f:
        matn = f.read()
    if not matn.strip():
        return {}
    try:
        m = json.loads(matn)
    except json.JSONDecodeError:
        return {}
    return m if isinstance(m, dict) else {}


def sozlama_oqi_eafp(yol: str) -> dict:
    """✅ Qisqa va atomik."""
    import json
    try:
        with open(yol, encoding="utf-8") as f:
            m = json.load(f)
        return m if isinstance(m, dict) else {}
    except (OSError, json.JSONDecodeError, UnicodeDecodeError):
        return {}


print(f"  LBYL versiyasi:  {len(sozlama_oqi_lbyl.__code__.co_code)} bayt-kod")
print(f"  EAFP versiyasi:  {len(sozlama_oqi_eafp.__code__.co_code)} bayt-kod")

import inspect
q1 = len(inspect.getsource(sozlama_oqi_lbyl).split("\n"))
q2 = len(inspect.getsource(sozlama_oqi_eafp).split("\n"))
print(f"\n  Kod qatorlari: {q1} vs {q2}")

print(f"\n  Sinov:")
import tempfile, json as _json

with tempfile.TemporaryDirectory() as tmp:
    p = Path(tmp)
    (p / "yaxshi.json").write_text('{"a": 1}', encoding="utf-8")
    (p / "buzilgan.json").write_text("{buzilgan}", encoding="utf-8")
    (p / "bosh.json").write_text("", encoding="utf-8")
    (p / "royxat.json").write_text("[1, 2]", encoding="utf-8")

    SINOVLAR = ["yaxshi.json", "buzilgan.json", "bosh.json",
                "royxat.json", "yoq.json", "."]

    print(f"    {'Fayl':<18} {'LBYL':<12} {'EAFP'}")
    print("    " + "─" * 44)
    for nom in SINOVLAR:
        yol = str(p / nom) if nom != "." else str(p)
        try:
            r1 = repr(sozlama_oqi_lbyl(yol))
        except Exception as e:
            r1 = f"❌ {type(e).__name__}"
        try:
            r2 = repr(sozlama_oqi_eafp(yol))
        except Exception as e:
            r2 = f"❌ {type(e).__name__}"
        print(f"    {nom:<18} {r1:<12} {r2}")

print(f"""
  ⭐ EAFP:
     • {q2} qator ({q1} o'rniga)
     • Poyga holati yo'q
     • Barcha holatlarni qamraydi
     • Yangi xato turi qo'shilsa — except ga qo'shiladi

  ⚠️ LBYL:
     • Har tekshiruv — poyga holati
     • Ba'zi holatlar unutiladi (papka, ruxsat, kodlash)
     • Uzunroq
""")


print("=== 6. Poyga holati: tekshiruv va foydalanish orasidagi oyna ===\n")


class BoshqaIpchaBilan(dict):
    """⭐ "Boshqa ipcha"ni DETERMINISTIK simulyatsiya qiladi.

    Real ipchalarda o'chirish aynan tekshiruv va foydalanish orasiga
    tushishi KAMDAN-KAM bo'ladi. Bu yerda biz uni ataylab o'sha
    lahzaga qo'yamiz — xato har safar takrorlanadi.
    """

    def __contains__(self, kalit):
        bor = super().__contains__(kalit)
        self.pop(kalit, None)               # ⚠️ shu lahzada boshqa ipcha o'chirdi
        return bor


def lbyl_ol(d, kalit):
    if kalit in d:                          # 1. tekshiruv — "bor"
        return d[kalit]                     # 2. ⚠️ endi yo'q!
    return "yo'q"


def eafp_ol(d, kalit):
    try:
        return d[kalit]                     # ⭐ bitta amal
    except KeyError:
        return "yo'q"


for nom, f in [("LBYL (if + [])", lbyl_ol), ("EAFP (try)", eafp_ol)]:
    d = BoshqaIpchaBilan(sessiya="abc123")
    try:
        natija = repr(f(d, "sessiya"))
    except KeyError as e:
        natija = f"❌ KeyError: {e}   ⚠️ POYGA HOLATI"
    print(f"    {nom:<16} → {natija}")

print(f"""
  ⭐ LBYL da `if k in d` VA `d[k]` — IKKI amal.
     Ular orasida holat o'zgarishi mumkin ("TOCTOU": time of check
     to time of use). Tekshiruv "bor" dedi — foydalanish paytida yo'q.

  ⭐ EAFP da `d[k]` — BITTA amal. Natija yoki qiymat, yoki KeyError —
     ikkalasi ham HAQIQIY holatni aks ettiradi.

  ⚠️ Nega real ipchalar bilan ko'rsatmadik? Chunki bunday xato
     juda kamdan-kam va tasodifiy chiqadi: CPython da GIL ipchalarni
     millisekundlab navbatma-navbat ishlatadi, va o'chirish aynan shu
     ikki amal orasiga tushishi uchun omad kerak. Aynan shuning uchun
     u XAVFLI — testlarda o'tadi, ishlab chiqarishda esa bir kun
     kutilmaganda qulaydi. Fayl tizimi, tarmoq va bazada (bir nechta
     jarayon ishlaganda) bu oyna ancha katta.
""")

Natijaning muhim qismi:

text
=== 2. Tezlik solishtiruvi ===

  500,000 chaqiruv:

  Holat                          LBYL       EAFP  Farq
  ────────────────────────────────────────────────────────
  Kalit BOR (100%)            0.111s     0.083s  EAFP 1.3× tez
  Kalit YO'Q (100%)           0.094s     0.268s  EAFP 2.8× sekin
  5% xato (aralash)            0.098s     0.112s  EAFP 1.14×
  50% xato                     0.089s     0.245s  EAFP 2.75×

=== ⭐ 4. Tayyor muqobillar ===

  Xatoli                 Xavfsiz muqobil                       Natija
  ──────────────────────────────────────────────────────────────────────────
  d[k]                   d.get(k, sukut)                       'sukut'
  next(it)               next(it, sukut)                       'sukut'
  lst[i]                 lst[i:i+1]                            []

=== 6. Poyga holati: tekshiruv va foydalanish orasidagi oyna ===

    LBYL (if + [])   → ❌ KeyError: 'sessiya'   ⚠️ POYGA HOLATI
    EAFP (try)       → 'abc123'

Nima ko'rsatdi: 2.5-bo'lim.

Misol 3 — Qayta ko'tarish va ichma-ich

python
"""raise, ichma-ich try va shartli ushlash."""

from __future__ import annotations

import errno
import os
import time
import traceback
from pathlib import Path

print("=== ⭐ 1. raise vs raise e ===\n")


def ichki():
    1 / 0


def orta_raise():
    try:
        ichki()
    except ZeroDivisionError:
        raise                                   # ⭐ asl traceback


def orta_raise_e():
    try:
        ichki()
    except ZeroDivisionError as e:
        raise e                                 # ⚠️ ortiqcha yozuv


def orta_raise_new():
    try:
        ichki()
    except ZeroDivisionError as e:
        raise RuntimeError("Yangi") from e      # ⭐ zanjir


for f, nom in [(orta_raise, "raise"), (orta_raise_e, "raise e"),
               (orta_raise_new, "raise X from e")]:
    try:
        f()
    except Exception as e:
        ramkalar = len(traceback.extract_tb(e.__traceback__))
        print(f"  {nom:<20} {ramkalar} ramka, "
              f"{type(e).__name__}")
        for q in traceback.format_exc().rstrip().split("\n")[-6:]:
            print(f"    {q}")
        print()

print(f"""  ⭐ FARQI:

     raise            asl traceback saqlanadi
     raise e          asl traceback ham saqlanadi, lekin "raise e"
                      qatori uchun BITTA ortiqcha ramka qo'shiladi
     raise X from e   yangi istisno + asl sabab zanjirda (__cause__)
""")


print("=== ⭐ 2. Shartli ushlash ===\n")


def fayl_ochir(yol: str) -> bool:
    """⭐ Faqat 'fayl yo'q' xatosini yutamiz."""
    try:
        os.remove(yol)
        return True
    except OSError as e:
        if e.errno != errno.ENOENT:             # ⭐ boshqasini uzatamiz
            raise
        return False


import tempfile

with tempfile.TemporaryDirectory() as tmp:
    p = Path(tmp)
    (p / "bor.txt").write_text("test")

    print(f"  fayl_ochir(mavjud fayl)  = {fayl_ochir(str(p / 'bor.txt'))}")
    print(f"  fayl_ochir(mavjud emas)  = {fayl_ochir(str(p / 'yoq.txt'))}")

    try:
        fayl_ochir(str(p))                      # ⚠️ papka
    except OSError as e:
        print(f"  fayl_ochir(papka)        → ✅ {type(e).__name__}: "
              f"errno={e.errno}")

print(f"""
  ⭐ NAQSH:
     except OSError as e:
         if e.errno != KUTILGAN:
             raise                  ⭐ boshqasini uzatamiz
         # faqat kutilganini ishlaymiz

  ⭐ Muqobil (3.3+):
     except FileNotFoundError:      ✅ aniqroq
""")


print("=== 3. Ichma-ich try ===\n")


def ichma_ich(bosqich_xato: int):
    """Uch bosqichli quvur — har birida tozalash."""
    izlar = []

    try:
        izlar.append("1: resurs ochildi")
        if bosqich_xato == 1:
            raise ValueError("1-bosqich")

        try:
            izlar.append("2: ma'lumot yuklandi")
            if bosqich_xato == 2:
                raise KeyError("2-bosqich")

            try:
                izlar.append("3: qayta ishlandi")
                if bosqich_xato == 3:
                    raise TypeError("3-bosqich")
                izlar.append("✅ muvaffaqiyat")
            except TypeError as e:
                izlar.append(f"   3-tozalash: {e}")
                raise                           # ⭐ yuqoriga

        except KeyError as e:
            izlar.append(f"   2-tozalash: {e}")
            raise

    except (ValueError, KeyError, TypeError) as e:
        izlar.append(f"   1-tozalash: {type(e).__name__}")
        izlar.append(f"❌ yakuniy: {e}")

    return izlar


for n in [0, 1, 2, 3]:
    print(f"  Xato {n}-bosqichda:" if n else "  Xatosiz:")
    for q in ichma_ich(n):
        print(f"    {q}")
    print()

print(f"""  ⭐ HAR DARAJADA:
     • O'z tozalashini bajaradi
     • raise bilan yuqoriga uzatadi
     • Asl istisno saqlanadi

  ⚠️ Bu naqsh uchun `finally` yoki `with` yaxshiroq (9.3-dars)
""")


print("=== ⭐ 4. Qayta urinish naqshi ===\n")


class VaqtinchalikXato(Exception):
    """Qayta urinish mumkin."""


class DoimiyXato(Exception):
    """Qayta urinish foydasiz."""


def notogri_xizmat(urinish: int, holat: list):
    """Uchinchi urinishda ishlaydi."""
    holat[0] += 1
    if holat[0] < 3:
        raise VaqtinchalikXato(f"Tarmoq xatosi (urinish {holat[0]})")
    return f"✅ Natija (urinish {holat[0]})"


def qayta_urin(f, urinishlar: int = 5, kutish: float = 0.001,
               qayta_urinilsin: tuple = (VaqtinchalikXato,)):
    """⭐ Faqat MA'LUM xatolarda qayta urinadi."""
    oxirgi = None
    for n in range(1, urinishlar + 1):
        try:
            return f(n)
        except qayta_urinilsin as e:            # ⭐ vaqtinchalik
            oxirgi = e
            if n < urinishlar:
                time.sleep(kutish * (2 ** (n - 1)))     # eksponensial
        except Exception:
            raise                               # ⭐ boshqasi — darhol
    raise RuntimeError(
        f"{urinishlar} urinish muvaffaqiyatsiz"
    ) from oxirgi


holat = [0]
natija = qayta_urin(lambda n: notogri_xizmat(n, holat))
print(f"  Vaqtinchalik xato: {natija}")

holat = [0]
try:
    qayta_urin(lambda n: notogri_xizmat(n, holat), urinishlar=2)
except RuntimeError as e:
    print(f"\n  Urinishlar yetmadi:")
    print(f"    ❌ {e}")
    print(f"    Sabab: {type(e.__cause__).__name__}: {e.__cause__}")


def doimiy_xato(n):
    raise DoimiyXato("Autentifikatsiya xatosi")


print(f"\n  Doimiy xato (qayta urinilmaydi):")
try:
    qayta_urin(doimiy_xato)
except DoimiyXato as e:
    print(f"    ✅ {type(e).__name__}: {e}   (darhol, urinishsiz)")

print(f"""
  ⭐ QAYTA URINISH QOIDALARI:

     ✅ Qayta urinish MUMKIN:
        ConnectionError, TimeoutError, 429/503 javoblar,
        vaqtinchalik baza xatolari

     ❌ Qayta urinish FOYDASIZ:
        ValueError, TypeError, autentifikatsiya, 400/404,
        dastur mantiqidagi xato

  ⭐ Eksponensial kutish: 1ms, 2ms, 4ms, 8ms, ...
""")


print("=== 5. Bir necha xatoni yig'ish ===\n")


def quvur(malumot: list) -> tuple[list, list]:
    """⭐ Xato bo'lsa TO'XTAMAYDI — yig'adi."""
    natija, xatolar = [], []
    for i, x in enumerate(malumot):
        try:
            natija.append(int(x) * 2)
        except (ValueError, TypeError) as e:
            xatolar.append((i, x, e))
    return natija, xatolar


MALUMOT = [1, "2", "uch", 4.5, None, "6", [7]]

natija, xatolar = quvur(MALUMOT)

print(f"  Kirish: {MALUMOT}\n")
print(f"  ✅ Natija ({len(natija)}): {natija}")
print(f"\n  ❌ Xatolar ({len(xatolar)}):")
for i, x, e in xatolar:
    print(f"    [{i}] {x!r:<10} {type(e).__name__}: {str(e)[:38]}")

print(f"\n  ⭐ ExceptionGroup (3.11+):")

import sys
if sys.version_info >= (3, 11):
    try:
        raise ExceptionGroup(
            "Quvurda xatolar",
            [e for _, _, e in xatolar],
        )
    except* ValueError as eg:
        print(f"    ValueError guruhi: {len(eg.exceptions)} ta")
    except* TypeError as eg:
        print(f"    TypeError guruhi: {len(eg.exceptions)} ta")
else:
    print(f"    ⚠️ Python 3.11+ kerak "
          f"(joriy: {sys.version_info.major}.{sys.version_info.minor})")

print(f"""
  ⭐ ExceptionGroup (PEP 654, 3.11):
     • Bir nechta istisnoni BIRGA ko'tarish
     • except* bilan turlar bo'yicha ajratish
     • asyncio.TaskGroup ishlatadi
""")


print("=== ⭐ 6. Kontekst qo'shish ===\n")


def sozlama_yukla(yol: str) -> dict:
    import json
    try:
        with open(yol, encoding="utf-8") as f:
            return json.load(f)
    except FileNotFoundError as e:
        raise RuntimeError(
            f"Sozlama fayli topilmadi: {yol}"
        ) from e
    except json.JSONDecodeError as e:
        raise RuntimeError(
            f"Sozlama fayli buzilgan: {yol} "
            f"(qator {e.lineno}, ustun {e.colno})"
        ) from e
    except PermissionError as e:
        raise RuntimeError(
            f"Sozlama fayliga ruxsat yo'q: {yol}"
        ) from e


with tempfile.TemporaryDirectory() as tmp:
    p = Path(tmp)
    (p / "buzilgan.json").write_text('{"a": 1,\n  "b": }',
                                     encoding="utf-8")

    for nom in ["yoq.json", "buzilgan.json"]:
        try:
            sozlama_yukla(str(p / nom))
        except RuntimeError as e:
            print(f"  {nom}:")
            print(f"    ❌ {e}")
            print(f"    Sabab: {type(e.__cause__).__name__}")

print(f"""
  ⭐ KONTEKST QO'SHISH NAQSHI:

     except AniqXato as e:
         raise UmumiyXato(
             f"Nima bo'lgani + QAYERDA + QANDAY tuzatish"
         ) from e

  ⭐ AFZALLIKLARI:
     • Foydalanuvchi tushunadi
     • Asl sabab saqlanadi (from e)
     • Ichki tafsilotlar yashiriladi
     • Yuqori qatlam bitta tur bilan ishlaydi
""")

Natijaning muhim qismi:

text
=== ⭐ 1. raise vs raise e ===

  raise                3 ramka, ZeroDivisionError
  raise e              4 ramka, ZeroDivisionError
  raise X from e       2 ramka, RuntimeError

=== ⭐ 4. Qayta urinish naqshi ===

  Vaqtinchalik xato: ✅ Natija (urinish 3)

  Urinishlar yetmadi:
    ❌ 2 urinish muvaffaqiyatsiz
    Sabab: VaqtinchalikXato: Tarmoq xatosi (urinish 2)

  Doimiy xato (qayta urinilmaydi):
    ✅ DoimiyXato: Autentifikatsiya xatosi   (darhol, urinishsiz)

=== 5. Bir necha xatoni yig'ish ===

  ✅ Natija (4): [2, 4, 8, 12]

  ❌ Xatolar (3):
    [2] 'uch'      ValueError: invalid literal for int()
    [4] None       TypeError: int() argument must be a string

Nima ko'rsatdi: 2.6, 2.7-bo'limlar.

Misol 4 — Amaliy: ishonchli ma'lumot yuklovchi

python
"""try/except ning barcha jihatlari bir loyihada."""

from __future__ import annotations

import csv
import io
import json
import logging
import time
from dataclasses import dataclass, field
from datetime import datetime, date
from decimal import Decimal, InvalidOperation
from pathlib import Path
from typing import Any, Callable, Iterator

print("=== MA'LUMOT YUKLOVCHI ===\n")

jurnal = logging.getLogger("yuklovchi")
jurnal.setLevel(logging.DEBUG)
_bufer = io.StringIO()
_h = logging.StreamHandler(_bufer)
_h.setFormatter(logging.Formatter("%(levelname)-8s %(message)s"))
jurnal.addHandler(_h)
jurnal.propagate = False


# ═══ ISTISNOLAR ═══

class YuklashXatosi(Exception):
    """Asosiy — foydalanuvchiga ko'rsatiladi."""


class VaqtinchalikXato(YuklashXatosi):
    """⭐ Qayta urinish mumkin."""


class MalumotXatosi(YuklashXatosi):
    """⭐ Ma'lumot yaroqsiz — qayta urinish foydasiz."""

    def __init__(self, xabar: str, qator: int = 0, ustun: str = ""):
        self.qator, self.ustun = qator, ustun
        joy = []
        if qator:
            joy.append(f"qator {qator}")
        if ustun:
            joy.append(f"ustun {ustun!r}")
        super().__init__(f"{xabar} ({', '.join(joy)})" if joy else xabar)


# ═══ NATIJA ═══

@dataclass
class Natija:
    """Yuklash natijasi."""

    yozuvlar: list[dict] = field(default_factory=list)
    xatolar: list[tuple[int, Exception]] = field(default_factory=list)
    ogohlantirishlar: list[str] = field(default_factory=list)
    urinishlar: int = 0
    vaqt_ms: float = 0.0

    @property
    def muvaffaqiyatli(self) -> bool:
        return bool(self.yozuvlar) and not self.xatolar

    @property
    def qisman(self) -> bool:
        return bool(self.yozuvlar) and bool(self.xatolar)

    def __str__(self):
        holat = ("✅ to'liq" if self.muvaffaqiyatli else
                 "⚠️ qisman" if self.qisman else "❌ muvaffaqiyatsiz")
        return (f"{holat}: {len(self.yozuvlar)} yozuv, "
                f"{len(self.xatolar)} xato, {self.vaqt_ms:.1f}ms")


# ═══ MAYDON O'GIRUVCHILAR ═══

def satr(q: Any) -> str:
    if q is None:
        raise ValueError("bo'sh qiymat")
    n = str(q).strip()
    if not n:
        raise ValueError("bo'sh satr")
    return n


def butun(q: Any) -> int:
    try:
        return int(str(q).strip().replace(" ", "").replace(",", ""))
    except (ValueError, TypeError) as e:
        raise ValueError(f"butun son emas: {q!r}") from e


def pul(q: Any) -> Decimal:
    try:
        return Decimal(str(q).strip().replace(" ", "").replace(",", ""))
    except (InvalidOperation, TypeError) as e:
        raise ValueError(f"summa emas: {q!r}") from e


def sana(q: Any) -> date:
    matn = str(q).strip()
    for fmt in ("%Y-%m-%d", "%d.%m.%Y", "%d/%m/%Y"):
        try:
            return datetime.strptime(matn, fmt).date()
        except ValueError:
            continue
    raise ValueError(f"sana formati noma'lum: {q!r}")


def mantiq(q: Any) -> bool:
    n = str(q).strip().lower()
    if n in ("1", "true", "ha", "yes", "y", "+"):
        return True
    if n in ("0", "false", "yo'q", "yoq", "no", "n", "-", ""):
        return False
    raise ValueError(f"mantiqiy qiymat emas: {q!r}")


# ═══ YUKLOVCHI ═══

class Yuklovchi:
    """⭐ Ishonchli ma'lumot yuklash."""

    SXEMA: dict[str, tuple[Callable, bool]] = {
        # nom: (o'giruvchi, majburiy)
        "id": (butun, True),
        "ism": (satr, True),
        "maosh": (pul, True),
        "ishga_kirgan": (sana, False),
        "faol": (mantiq, False),
    }

    def __init__(self, *, urinishlar: int = 3, kutish: float = 0.001,
                 maks_xato: int | None = None, qatiy: bool = False):
        self.urinishlar = urinishlar
        self.kutish = kutish
        self.maks_xato = maks_xato
        self.qatiy = qatiy

    # ── Bitta yozuv ──

    def _yozuv(self, xom: dict, qator: int) -> dict:
        """⭐ Har maydon alohida try — aniq xato joyi."""
        natija = {}
        for nom, (ogir, majburiy) in self.SXEMA.items():
            if nom not in xom or xom[nom] in (None, ""):
                if majburiy:
                    raise MalumotXatosi(
                        "majburiy maydon yo'q", qator, nom
                    )
                natija[nom] = None
                continue
            try:
                natija[nom] = ogir(xom[nom])
            except ValueError as e:
                raise MalumotXatosi(str(e), qator, nom) from e
        return natija

    # ── Manbalar ──

    def _csv(self, matn: str) -> Iterator[tuple[int, dict]]:
        try:
            oquvchi = csv.DictReader(io.StringIO(matn))
            for i, q in enumerate(oquvchi, 2):
                yield i, q
        except csv.Error as e:
            raise MalumotXatosi(f"CSV xatosi: {e}") from e

    def _json(self, matn: str) -> Iterator[tuple[int, dict]]:
        try:
            m = json.loads(matn)
        except json.JSONDecodeError as e:
            raise MalumotXatosi(
                f"JSON xatosi: {e.msg}", e.lineno
            ) from e
        if isinstance(m, dict):
            m = [m]
        if not isinstance(m, list):
            raise MalumotXatosi("JSON massiv yoki obyekt bo'lsin")
        for i, q in enumerate(m, 1):
            if not isinstance(q, dict):
                raise MalumotXatosi(f"obyekt kutildi: {type(q).__name__}",
                                    i)
            yield i, q

    # ── Asosiy ──

    def yukla(self, manba: str | Path, format: str = "auto") -> Natija:
        """⭐ Qayta urinish + xatolarni yig'ish."""
        boshlanish = time.perf_counter()
        n = Natija()

        # 1. Manbani o'qish (qayta urinish bilan)
        matn = None
        for urinish in range(1, self.urinishlar + 1):
            n.urinishlar = urinish
            try:
                matn = self._oqi(manba)
                break
            except VaqtinchalikXato as e:
                jurnal.warning("Urinish %d/%d: %s",
                               urinish, self.urinishlar, e)
                if urinish < self.urinishlar:
                    time.sleep(self.kutish * (2 ** (urinish - 1)))
            except YuklashXatosi:
                raise                           # ⭐ doimiy — darhol
        else:
            n.vaqt_ms = (time.perf_counter() - boshlanish) * 1000
            raise VaqtinchalikXato(
                f"{self.urinishlar} urinish muvaffaqiyatsiz"
            )

        # 2. Formatni aniqlash
        if format == "auto":
            format = "json" if matn.lstrip()[:1] in "[{" else "csv"
            n.ogohlantirishlar.append(f"format aniqlandi: {format}")

        # 3. Yozuvlarni qayta ishlash
        tahlilchi = {"csv": self._csv, "json": self._json}[format]
        try:
            for qator, xom in tahlilchi(matn):
                try:
                    n.yozuvlar.append(self._yozuv(xom, qator))
                except MalumotXatosi as e:
                    n.xatolar.append((qator, e))
                    jurnal.debug("Qator %d: %s", qator, e)
                    if self.qatiy:
                        raise
                    if (self.maks_xato is not None
                            and len(n.xatolar) >= self.maks_xato):
                        n.ogohlantirishlar.append(
                            f"xato chegarasi ({self.maks_xato}) — to'xtatildi"
                        )
                        break
        except MalumotXatosi as e:
            if self.qatiy:
                raise
            n.xatolar.append((0, e))

        n.vaqt_ms = (time.perf_counter() - boshlanish) * 1000
        return n

    def _oqi(self, manba: str | Path) -> str:
        """⭐ Xatolarni ANIQ turlarga o'giradi."""
        if isinstance(manba, str) and (
            manba.lstrip()[:1] in "[{" or "," in manba.split("\n")[0]
        ):
            return manba                        # to'g'ridan-to'g'ri matn

        yol = Path(manba)
        try:
            return yol.read_text(encoding="utf-8")
        except FileNotFoundError as e:
            raise MalumotXatosi(f"fayl topilmadi: {yol}") from e
        except IsADirectoryError as e:
            raise MalumotXatosi(f"papka, fayl emas: {yol}") from e
        except PermissionError as e:
            # ⚠️ Windows'da papkani o'qishga urinish ham PermissionError
            #    beradi (Linux/macOS da — IsADirectoryError)
            if yol.is_dir():
                raise MalumotXatosi(f"papka, fayl emas: {yol}") from e
            raise MalumotXatosi(f"ruxsat yo'q: {yol}") from e
        except UnicodeDecodeError as e:
            raise MalumotXatosi(
                f"kodlash xatosi ({e.encoding}, bayt {e.start})"
            ) from e
        except OSError as e:
            raise VaqtinchalikXato(f"o'qish xatosi: {e}") from e


# ═══ SINOVLAR ═══

CSV_YAXSHI = """id,ism,maosh,ishga_kirgan,faol
1,Aziz Karimov,8500000,2023-03-15,ha
2,Malika Yusupova,7 000 000,15.01.2024,1
3,Bobur Aliyev,9500000,2022-06-01,yo'q"""

CSV_MUAMMOLI = """id,ism,maosh,ishga_kirgan,faol
1,Aziz,8500000,2023-03-15,ha
xato,Malika,7000000,2024-01-15,1
3,,9500000,2022-06-01,ha
4,Dilnoza,ko'p pul,2023-01-01,ha
5,Sardor,6000000,noto'g'ri-sana,ha
6,Nilufar,5500000,2023-05-05,ehtimol
7,Jasur,7500000,2023-07-07,ha"""

JSON_YAXSHI = json.dumps([
    {"id": 10, "ism": "Kamola", "maosh": "12000000",
     "ishga_kirgan": "2021-09-01", "faol": True},
    {"id": 11, "ism": "Rustam", "maosh": "8000000"},
])

JSON_BUZILGAN = '{"id": 1, "ism": }'


print("1. To'liq muvaffaqiyat:\n")

y = Yuklovchi()
n = y.yukla(CSV_YAXSHI)
print(f"  {n}\n")
for z in n.yozuvlar:
    print(f"    {z['id']}. {z['ism']:<18} {z['maosh']:>12,} "
          f"{z['ishga_kirgan']} {z['faol']}")


print("\n\n2. ⭐ Qisman muvaffaqiyat (xatolar yig'iladi):\n")

n = y.yukla(CSV_MUAMMOLI)
print(f"  {n}\n")

print(f"  ✅ Yuklandi ({len(n.yozuvlar)}):")
for z in n.yozuvlar:
    print(f"    {z['id']}. {z['ism']:<12} {z['maosh']:>12,}")

print(f"\n  ❌ Xatolar ({len(n.xatolar)}):")
for qator, e in n.xatolar:
    print(f"    {e}")

print(f"\n  ⭐ Ish TO'XTAMADI — {len(n.xatolar)} xatoga qaramay "
      f"{len(n.yozuvlar)} yozuv yuklandi")


print("\n\n3. Xato chegarasi:\n")

for maks in [None, 2, 1]:
    y2 = Yuklovchi(maks_xato=maks)
    n2 = y2.yukla(CSV_MUAMMOLI)
    print(f"  maks_xato={str(maks):<6} → {n2}")
    if n2.ogohlantirishlar:
        for o in n2.ogohlantirishlar:
            print(f"    ⚠️ {o}")


print("\n\n4. Qat'iy rejim:\n")

y3 = Yuklovchi(qatiy=True)
try:
    y3.yukla(CSV_MUAMMOLI)
except MalumotXatosi as e:
    print(f"  ❌ {type(e).__name__}: {e}")
    print(f"     qator={e.qator}, ustun={e.ustun!r}")
    print(f"     sabab: {type(e.__cause__).__name__}: {e.__cause__}")


print("\n\n5. JSON manbasi:\n")

n = y.yukla(JSON_YAXSHI)
print(f"  Yaxshi JSON: {n}")
for z in n.yozuvlar:
    print(f"    {z['id']}. {z['ism']:<10} {z['maosh']:>12,} "
          f"sana={z['ishga_kirgan']}")

print(f"\n  Buzilgan JSON:")
n = y.yukla(JSON_BUZILGAN)
print(f"    {n}")
for _, e in n.xatolar:
    print(f"    ❌ {e}")


print("\n\n6. ⭐ Fayl xatolari (aniq turlar):\n")

import tempfile

with tempfile.TemporaryDirectory() as tmp:
    p = Path(tmp)
    (p / "yaxshi.csv").write_text(CSV_YAXSHI, encoding="utf-8")
    (p / "buzilgan.csv").write_bytes(b"id,ism\n1,\xff\xfe")

    FAYLLAR = [
        ("yaxshi.csv",  "mavjud fayl"),
        ("yoq.csv",     "mavjud emas"),
        (".",           "papka"),
        ("buzilgan.csv", "kodlash xatosi"),
    ]

    for nom, tavsif in FAYLLAR:
        yol = p / nom if nom != "." else p
        try:
            n = y.yukla(yol)
            r = f"✅ {n}"
        except YuklashXatosi as e:
            r = f"❌ {type(e).__name__}: {e}"
        print(f"  {tavsif:<18} {r}")


print("\n\n7. Qayta urinish:\n")


class NosozYuklovchi(Yuklovchi):
    """Sinov uchun — birinchi 2 urinishda xato."""

    def __init__(self, **kw):
        super().__init__(**kw)
        self._urinish = 0

    def _oqi(self, manba):
        self._urinish += 1
        if self._urinish < 3:
            raise VaqtinchalikXato(f"tarmoq xatosi #{self._urinish}")
        return super()._oqi(manba)


ny = NosozYuklovchi(urinishlar=5)
n = ny.yukla(CSV_YAXSHI)
print(f"  {n}")
print(f"    urinishlar: {n.urinishlar}")

ny2 = NosozYuklovchi(urinishlar=2)
try:
    ny2.yukla(CSV_YAXSHI)
except VaqtinchalikXato as e:
    print(f"\n  urinishlar=2 → ❌ {e}")


print("\n\n8. Jurnal:\n")

for q in _bufer.getvalue().rstrip().split("\n")[:10]:
    print(f"  {q}")
qolgan = len(_bufer.getvalue().rstrip().split("\n")) - 10
if qolgan > 0:
    print(f"  ... yana {qolgan} qator")

print(f"""

  ⭐ BU LOYIHADA:

     ISTISNO IERARXIYASI:
       YuklashXatosi
        ├── VaqtinchalikXato    ⭐ qayta urinish MUMKIN
        └── MalumotXatosi       ⭐ qayta urinish FOYDASIZ

     ANIQ TURLAR:
       FileNotFoundError, IsADirectoryError, PermissionError,
       UnicodeDecodeError, OSError → MalumotXatosi/VaqtinchalikXato

     from e:
       Har o'rashda asl sabab saqlanadi

     XATOLARNI YIG'ISH:
       Bitta yozuv xato → qolganlari yuklanadi
       Xato chegarasi va qat'iy rejim

     QAYTA URINISH:
       Faqat VaqtinchalikXato uchun
       Eksponensial kutish
       for/else naqshi

     JURNAL:
       warning — qayta urinish
       debug   — har xato

  ⭐ YALANG'OCH except HECH QAYERDA ISHLATILMAGAN
""")

Natijaning muhim qismi:

text
2. ⭐ Qisman muvaffaqiyat (xatolar yig'iladi):

  ⚠️ qisman: 2 yozuv, 5 xato, 1.2ms

  ✅ Yuklandi (2):
    1. Aziz            8,500,000
    7. Jasur           7,500,000

  ❌ Xatolar (5):
    butun son emas: 'xato' (qator 3, ustun 'id')
    majburiy maydon yo'q (qator 4, ustun 'ism')
    summa emas: "ko'p pul" (qator 5, ustun 'maosh')

  ⭐ Ish TO'XTAMADI — 5 xatoga qaramay 2 yozuv yuklandi

6. ⭐ Fayl xatolari (aniq turlar):

  mavjud fayl        ✅ ✅ to'liq: 3 yozuv, 0 xato
  mavjud emas        ❌ MalumotXatosi: fayl topilmadi
  papka              ❌ MalumotXatosi: papka, fayl emas
  kodlash xatosi     ❌ MalumotXatosi: kodlash xatosi (utf-8, bayt 9)

7. Qayta urinish:

  ✅ to'liq: 3 yozuv, 0 xato, 4.1ms
    urinishlar: 3

Nima ko'rsatdi: 2.2, 2.3, 2.6, 2.7-bo'limlar.


5. To'g'ri va noto'g'ri tushunishlar

Noto'g'ri fikr To'g'risi
"except: — qulay qisqartma" BaseException — Ctrl+C ni ham ushlaydi
"except Exception: xavfsiz" Keng; faqat yuqori darajada + jurnal bilan
"except tartibi ahamiyatsiz" Avlod avval yozilishi kerak
"try sekin" Istisno bo'lmasa — deyarli bepul
"LBYL xavfsizroq" Poyga holati; EAFP atomik
"raise e traceback'ni yo'qotadi" Python 3 da saqlaydi — faqat ortiqcha yozuv qo'shadi
"e blokdan keyin ham bor" Avtomatik del e
"Xato bo'lsa to'xtash kerak" Ba'zan yig'ib davom etish yaxshiroq

6. Keng tarqalgan xatolar va yechimlari

1. Yalang'och except:

python
except:                             # ❌
except Exception as e:              # ⚠️ yuqori darajada
except ValueError as e:             # ✅

2. Jimgina yutish

python
except Exception:
    pass                            # ⚠️ xato yo'qoldi
except Exception as e:
    jurnal.exception("...")         # ✅

3. Noto'g'ri tartib

python
except ValueError: ...              # ⚠️ birinchi
except JSONDecodeError: ...         # ❌ o'lik kod
                                    # ✅ teskari

4. Juda keng try

python
try:
    a = f(); b = g(); c = h()       # ⚠️ qaysi biri?
except Exception: ...
                                    # ✅ alohida try yoki aniq turlar

5. raise e

python
except ValueError as e:
    raise e                         # ⚠️ ortiqcha traceback yozuvi
    raise                           # ✅ toza

6. e ni tashqarida ishlatish

python
except ValueError as e: pass
print(e)                            # ❌ NameError
xato = e                            # ✅ ichkarida boshqa nomga

7. print bilan xato

python
except Exception as e:
    print(f"Xato: {e}")             # ⚠️ traceback yo'q
    jurnal.exception("Xato")        # ✅

8. Muqobil borida try

python
try: return d[k]
except KeyError: return sukut       # ⚠️ tez-tez bo'lsa
return d.get(k, sukut)              # ✅

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 9.1-dars (o'tilgan): traceback va istisno turlari
  • 9.3-dars: else va finally
  • 9.4-9.5: bir nechta istisno, raise
  • 9.7: istisnolar ierarxiyasi
  • 10-qism: kontekst menejerlari (with)
  • 17-qism: pytest.raises, xatolarni testlash
  • logging, contextlib, retrying/tenacity

8. Eng yaxshi amaliyotlar

  1. Hech qachon except: yozmang. except Exception: — faqat yuqori darajada.

  2. Eng aniq turni ushlang. FileNotFoundError, ValueError emas.

  3. Avlodni ota-sinfdan oldin. JSONDecodeError → ValueError.

  4. try blokini qisqa tuting. Faqat xato berishi mumkin bo'lgan qator.

  5. Xatoni jurnalga yozing. logging.exception() — print emas.

  6. raise ishlating, raise e emas. Traceback toza bo'lsin.

  7. EAFP — sukut tanlov. LBYL — xato tez-tez bo'lsa.

  8. Kontekst qo'shing. raise UmumiyXato(...) from e.


9. Amaliy topshiriq

Vazifa 1: Natijani bashorat qiling

python
1.  try:
        print("a"); 1/0; print("b")
    except ZeroDivisionError: print("c")
    print("d")
2.  try: 1/0
    except ValueError: print("v")
    except ZeroDivisionError: print("z")
3.  try: 1/0
    except Exception: print("e")
    except ZeroDivisionError: print("z")
4.  try: 1/0
    except ZeroDivisionError as e: pass
    print(type(e))
5.  try:
        try: 1/0
        except ZeroDivisionError: raise ValueError("v")
    except ValueError as e: print(type(e.__context__).__name__)
6.  try: raise SystemExit(1)
    except Exception: print("ushlandi")
7.  try: raise SystemExit(1)
    except: print("ushlandi")
8.  d = {}
    try: d["a"]
    except (KeyError, IndexError) as e: print(type(e).__name__)
9.  try: raise KeyError("k")
    except LookupError as e: print(type(e).__name__, e)
10. def f():
        try: return 1
        except: return 2
    print(f())
11. try:
        raise ValueError("a")
    except ValueError as e:
        e.add_note("izoh")
        print(e.__notes__)
12. import json
    try: json.loads("{")
    except ValueError as e: print(type(e).__name__)
Javoblar
  1. a c d — b bajarilmaydi
  2. z
  3. e — ZeroDivisionError bloki o'lik kod
  4. NameError — e o'chirilgan
  5. ZeroDivisionError
  6. Ushlanmaydi — dastur chiqadi (SystemExit — BaseException)
  7. ushlandi — yalang'och except
  8. KeyError
  9. KeyError 'k' — LookupError ota-sinf
  10. 1
  11. ['izoh'] (3.11+)
  12. JSONDecodeError

Vazifa 2: Xatolarni tuzating

python
1.  try: ish()
    except: pass
2.  try: ish()
    except Exception as e: print(f"Xato: {e}")
3.  try:
        m = json.loads(s)
    except ValueError: ...
    except json.JSONDecodeError: ...
4.  try:
        a = f(); b = g(); c = h()
    except Exception: ...
5.  except ValueError as e:
        tozala()
        raise e
6.  try: return d[k]
    except KeyError: return None
7.  while True:
        try: ish()
        except: continue
8.  try: ish()
    except Exception as e: xato = e
    print(xato)
Javoblar
python
1.  except (ValueError, KeyError) as e: jurnal.exception(...)
2.  jurnal.exception("Xato")   — traceback bilan
3.  JSONDecodeError ni AVVAL
4.  Har birini alohida try yoki aniq turlar
5.  raise   (e siz)
6.  return d.get(k)
7.  except Exception:  (KeyboardInterrupt o'tsin)
8.  xato = None  ni oldindan e'lon qiling

Vazifa 3: Xavfsiz o'giruvchi

Yozing:

  1. xavfsiz_int(q, sukut=0), xavfsiz_float, xavfsiz_sana
  2. Har biri aniq istisno turlarini ushlasin
  3. Xato sababini qaytarish imkoniyati
  4. Ro'yxat uchun ommaviy versiya
  5. Statistika: muvaffaqiyat/xato
  6. try bloklari minimal bo'lsin

Vazifa 4: except tekshiruvchisi

Vosita yozing (AST bilan):

  1. Yalang'och except: larni topsin
  2. except Exception: pass naqshini
  3. Noto'g'ri tartibni (ota-sinf avval)
  4. Juda keng try bloklarini (>5 qator)
  5. raise e (o'rniga raise)
  6. Muqobil bor joylarda try (d[k] → d.get)

Vazifa 5: Qayta urinish dekoratori

  1. @qayta_urin(urinishlar=3, kutish=1.0)
  2. Faqat berilgan istisnolarda
  3. Eksponensial kutish + jitter
  4. Har urinishni jurnalga
  5. Yakuniy xato zanjirda asl sababni saqlasin
  6. async versiyasi

Vazifa 6: Xatolarni yig'uvchi

  1. Kontekst menejeri: with XatoYiguvchi() as y:
  2. Blok ichidagi xatolarni yig'sin
  3. Chegara: N xatodan keyin ko'tarish
  4. Guruhlash: tur bo'yicha
  5. Hisobot: eng ko'p uchraydigan
  6. ExceptionGroup bilan ko'tarish (3.11+)

Vazifa 7: O'ylash

Nega Python except: (yalang'och) sintaksisini taqiqlamadi, agar u shu qadar xavfli bo'lsa?

Javob

Chunki u ba'zan haqiqatan kerak, va Python "kattalar tili" tamoyiliga amal qiladi.

1. Qachon except: haqiqatan kerak

a) Yakuniy tozalash (framework darajasida):

python
def ishga_tushir():
    resurs = ochish()
    try:
        asosiy_ish()
    except:                         # ⭐ HAMMASI
        resurs.yop()                # tozalash
        raise                       # ⭐ QAYTA ko'tarish

Muhim: raise bilan qayta ko'tariladi. Faqat tozalash uchun.

Lekin finally yaxshiroq:

python
try:
    asosiy_ish()
finally:
    resurs.yop()                    # ✅ soddaroq

b) Ipcha ishlovchisi:

python
def ipcha_ishi():
    try:
        ish()
    except:                         # ⭐ ipcha O'LMASLIGI kerak
        jurnal.exception("Ipchada xato")

Ipchada ushlanmagan istisno — ipcha jimgina o'ladi. Lekin except BaseException: ham bir xil.

c) __del__ va tozalash metodlari:

python
def __del__(self):
    try:
        self.yop()
    except:                         # ⭐ __del__ da xato yutiladi
        pass                        #    baribir ko'rsatilmaydi

d) Interaktiv REPL, test runner:

python
while True:
    try:
        kod = input(">>> ")
        exec(kod)
    except SystemExit:
        raise                       # ⭐ chiqish ruxsat
    except:
        traceback.print_exc()       # ⭐ boshqa hammasi ko'rsatiladi

2. except BaseException: — aniqroq muqobil

python
except:                             # ⚠️ niyat noaniq
except BaseException:               # ✅ ANIQ — "hammasini bilaman"

Ikkalasi texnik jihatdan bir xil, lekin ikkinchisi niyatni bildiradi.

ruff/flake8 E722 qoidasi aynan shuni talab qiladi:

E722 do not use bare 'except'

3. Nega taqiqlanmadi

a) Orqaga moslik

except: — Python 1.0 dan beri bor. Uni taqiqlash millionlab qator kodni buzardi.

b) "Consenting adults"

8.10-darsda ko'rgan falsafa: Python dasturchini cheklamaydi, ogohlantiradi.

c) Linterlar hal qiladi

bash
ruff check --select E722            # bare except
pylint --enable=W0702               # bare-except
flake8                              # E722

Barcha zamonaviy linterlar buni sukut bo'yicha tekshiradi.

d) Ba'zan kerak (yuqoridagi holatlar)

4. Python 3 dagi yaxshilanishlar

Python except: ni taqiqlamadi, lekin uni kamroq kerak qildi:

a) finally (Python 1.5) — tozalash uchun

python
try:
    ish()
finally:
    tozala()                        # ✅ except: kerak emas

b) with (Python 2.5, PEP 343) — resurslar uchun

python
with ochish() as r:
    ish()                           # ✅ avtomatik yopiladi

c) contextlib.suppress (3.4) — ataylab yutish

python
from contextlib import suppress

with suppress(FileNotFoundError):
    os.remove(yol)                  # ✅ aniq va qisqa

# o'rniga:
try:
    os.remove(yol)
except FileNotFoundError:
    pass

d) missing_ok, exist_ok (3.5-3.8) — tayyor muqobillar

python
Path(yol).unlink(missing_ok=True)   # ✅ try kerak emas
Path(p).mkdir(exist_ok=True)

e) ExceptionGroup va except* (3.11) — ko'p istisno

5. Boshqa tillar

Til Yalang'och ushlash Taqiqmi
Python except: Linter ogohlantiradi
Java catch (Throwable t) Ogohlantirish
C# catch { } Ogohlantirish
JavaScript catch (e) Yagona usul
Go recover() Faqat panic
Rust Yo'q Result<T, E>

JavaScript eng qiziq:

javascript
try {
    ish();
} catch (e) {                       // ⭐ HAR DOIM hammasi
    if (e instanceof TypeError) {   // ⚠️ qo'lda tekshirish
        ...
    } else {
        throw e;                    // ⚠️ qo'lda qayta ko'tarish
    }
}

JavaScript da turlar bo'yicha ushlash yo'q — bu Python dan yomonroq.

Rust — butunlay boshqa yondashuv:

rust
match fayl_oqi(yol) {
    Ok(matn) => ...,
    Err(e) => match e.kind() {
        ErrorKind::NotFound => ...,     // ⭐ kompilyator BARCHA
        ErrorKind::PermissionDenied => ...,  //   holatlarni talab qiladi
        _ => ...,
    }
}

Rust da istisnolar yo'q — xatolar qiymat sifatida qaytariladi va kompilyator ularni e'tiborsiz qoldirishga yo'l qo'ymaydi.

6. Statistika

GitHub dagi Python kodida (taxminiy):

Naqsh Uchrash
except Exception: ~45%
Aniq tur ~40%
except: ~12%
except BaseException: ~3%

12% — bu millionlab joy. Ko'pchiligi xato.

7. except: ning haqiqiy narxi

python
# ⚠️ Real hodisa (soddalashtirilgan):
def malumot_yukla():
    try:
        return baza.sorov("SELECT ...")
    except:
        return []                   # ⚠️ bo'sh ro'yxat


# Nima bo'ldi:
# 1. Baza parol o'zgardi → AuthError
# 2. except: uni yutdi
# 3. Funksiya [] qaytardi
# 4. Hisobot "0 ta yozuv" ko'rsatdi
# 5. ⚠️ Hech kim 3 kun sezmadi

Eng yomon xato turi: dastur ishlaydi, lekin noto'g'ri.

8. Amaliy qoidalar

python
# ❌ HECH QACHON
except:
    pass

# ⚠️ Faqat qayta ko'tarish bilan
except:
    tozala()
    raise

# ⚠️ Faqat eng yuqori darajada + jurnal
def main():
    try:
        ish()
    except Exception:
        jurnal.exception("Kutilmagan xato")
        return 1
    return 0

# ✅ Odatiy holat
except (ValueError, KeyError) as e:
    jurnal.warning("...", exc_info=e)

# ✅ Ataylab yutish
with contextlib.suppress(FileNotFoundError):
    os.remove(yol)

9. Linterni sozlash

toml
# pyproject.toml
[tool.ruff.lint]
select = [
    "E722",     # bare except
    "BLE",      # blind except (flake8-blind-except)
    "TRY",      # tryceratops — try/except antipatternlari
]

[tool.ruff.lint.per-file-ignores]
"framework/runner.py" = ["E722"]    # ⭐ ataylab

10. Xulosa

except: taqiqlanmagan, chunki:

  1. Ba'zan kerak — framework, ipcha, __del__
  2. Orqaga moslik — Python 1.0 dan beri
  3. "Consenting adults" — cheklash emas, ogohlantirish
  4. Linterlar hal qiladi — E722 sukut bo'yicha yoqilgan

Lekin Python uni kamroq kerak qildi: finally, with, contextlib.suppress, missing_ok=True, ExceptionGroup.

Amaliy qoida: except: yozayotgan bo'lsangiz — to'xtang va so'rang:

  1. finally yoki with yetadimi?
  2. contextlib.suppress(AniqTur) yetadimi?
  3. except Exception: yetadimi?
  4. raise bilan qayta ko'tarayapmanmi?

To'rt savolning hech biriga "yo'q" bo'lsa — ehtimol except: xato.

Nimani mustahkamlaydi: 2.2, 2.7-bo'limlar.


Xulosa

Bu darsda try/except ni o'rgandik.

Eng muhim uch fikr:

  1. Yalang'och except: — except BaseException: bilan bir xil. U KeyboardInterrupt ni ushlaydi (Ctrl+C ishlamaydi), SystemExit ni to'sadi (dastur to'xtamaydi) va sizning typolaringizni (NameError) jimgina yutadi. Eng aniq turni ushlang; except Exception: — faqat eng yuqori darajada va doim jurnal bilan.

  2. except tartibi muhim: aniqdan umumiyga. JSONDecodeError — ValueError avlodi, shuning uchun u avval yozilishi kerak; teskari bo'lsa avlod bloki hech qachon ishlamaydi. Bu — jimgina o'lik kod.

  3. EAFP — sukut tanlov, lekin mutlaq emas. try/except istisno bo'lmasa deyarli bepul va poyga holatini yo'q qiladi (tekshiruv va amal bitta atomik qadamda). Lekin xato tez-tez bo'lsa (~50%) — if sezilarli tezroq, va d.get(), next(it, sukut), Path.unlink(missing_ok=True) kabi tayyor muqobillar bor.

Keyingi darsda else va finally bloklarini ko'ramiz: qachon ular kerak, finally va return o'rtasidagi nozik munosabat va resurslarni to'g'ri tozalash.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
9.2-dars: try / except — IlmHamroh