IlmHamroh
Python kursi/Malumot formatlari6/8-dars21 daqiqa
Mundarija (22)

16.6-dars: YAML va TOML

16-QISM — MA'LUMOT FORMATLARI · 6-dars


1. Kirish va motivatsiya

JSON mashinalar orasida ajoyib, lekin odam yozadigan sozlama uchun noqulay: qo'shtirnoqlar, vergullar, izohlar yo'q. Shuning uchun konfiguratsiya uchun ikki format tug'ildi: YAML (Docker Compose, Kubernetes, CI/CD, Ansible) va TOML (pyproject.toml, cargo, ko'p Python vositasi).

Ikkalasi ham "odam uchun qulay" deb ataladi, lekin ular butunlay boshqacha falsafaga ega — va YAML ning "qulayligi" mashhur tuzoqlar keltirib chiqaradi.

Real vaziyat. Bir jamoa Kubernetes sozlamasini YAML da yozardi. Uch alohida voqea:

  • Mamlakatlar ro'yxatida - NO (Norvegiya) yozildi — YAML uni False deb o'qidi. Bu haqiqiy, mashhur "Norway problem".
  • Versiya raqami version: 1.10 yozildi — YAML uni 1.1 (float) qildi, oxirgi nol yo'qoldi.
  • Feature flag enabled: yes yozildi — kimdir uni "yes" (satr) deb kutdi, YAML esa True qildi.

Boshqa loyihada pyproject.toml da bog'liqlik versiyasi bilan muammo bo'ldi — bu safar TOML qat'iy turlari tufayli xato darhol, aniq joyda ko'rindi.

Bu darsda YAML va TOML ni, ularning tuzoqlarini va qaysi birini qachon tanlashni o'rganamiz.

Bu darsda:

  • YAML: safe_load, tuzilma, blok skalyarlar
  • YAML tuzoqlari: yes/no, Norway, sexagesimal, versiya
  • Xavfsizlik: safe_load vs load
  • YAML anchor va merge (<<)
  • TOML: tomllib (o'qish), tomli_w (yozish), qat'iy turlar
  • TOML: null yo'q, takroriy kalit xatosi
  • Amaliy: sozlamani yuklovchi va tekshiruvchi
  • YAML vs TOML vs JSON — qachon qaysi biri

ℹ PyYAML va tomli_w — tashqi kutubxonalar (pip install pyyaml tomli_w). tomllib — Python 3.11+ standart kutubxonasida, lekin faqat o'qish uchun.


2. Nazariya — chuqur tushuntirish

2.1. YAML asoslari

YAML — chekinish (bo'shliq) bilan tuzilmani ifodalaydi, qo'shtirnoq va vergul shart emas:

yaml
loyiha: Wisar
port: 8000
teglar:
  - python
  - web
baza:
  host: localhost
  port: 5432
python
import yaml
malumot = yaml.safe_load(matn)        # ⭐ har doim safe_load
matn = yaml.safe_dump(malumot, allow_unicode=True, sort_keys=False)
Xususiyat Izoh
Chekinish Ichma-ichlikni bildiradi ( TAB emas, bo'shliq)
- Ro'yxat elementi
kalit: qiymat Lug'at
# Izoh
| blok Yangi qatorlar saqlanadi
> folded Yangi qatorlar bo'shliqqa aylanadi

2.2. YAML turlarni "taxmin qiladi"

Bu YAML ning eng katta muammosi. PyYAML YAML 1.1 ni qo'llaydi va qo'shtirnoqsiz qiymatlarning turini o'zi aniqlaydi:

Yozilgan YAML o'qiydi
yes, on, true, True, TRUE True (bool)
no, off, false False (bool)
NO False — Norway problem (Norvegiya kodi)
1.10 1.1 (float) — oxirgi nol yo'qoladi
22:22 1342 (sexagesimal — 22×60+22)
2026-09-17 datetime.date
null, ~ None
0o17, 0xFF oktal/o'n oltilik son

Yechim: qiymatni qo'shtirnoqqa oling — "NO", "1.10", "yes" — shunda satr bo'lib qoladi.

2.3. Blok skalyarlar

yaml
literal: |
  birinchi qator
  ikkinchi qator
folded: >
  bu uzun matn
  bitta qatorga birlashadi
Belgi Natija
| "birinchi qator\nikkinchi qator\n" — yangi qatorlar saqlanadi
> "bu uzun matn bitta qatorga birlashadi\n" — bo'shliqqa aylanadi

2.4. YAML xavfsizligi

YAML nafaqat ma'lumot, balki Python obyektlarini ham ifodalashi mumkin: !!python/object/apply:os.system. Oddiy yaml.load bularni bajaradi — bu pickle kabi masofadan kod bajarish xavfi.

python
yaml.load(ishonchsiz)          # ❌ kod bajarishi mumkin
yaml.safe_load(ishonchsiz)     # ✅ faqat oddiy turlar; xavfli teg → ConstructorError

Har doim safe_load va safe_dump. yaml.load ni faqat Loader= bilan va faqat o'zingiz yozgan ma'lumot uchun ishlating.

2.5. Anchor va merge

YAML takrorni kamaytirish uchun anchor (&), havola (*) va merge (<<) beradi:

yaml
default: &def
  timeout: 30
  retry: 3
servis_a:
  <<: *def
  host: a.local

servis_a → {timeout: 30, retry: 3, host: a.local}. Anchor lar takror kengayishi (YAML "billion laughs") xavfini ham keltiradi — ishonchsiz YAML da ehtiyot bo'ling.

2.6. TOML — qat'iy va aniq

TOML ("Tom's Obvious Minimal Language") YAML ning aksi: aniq, qat'iy turlar, taxmin yo'q.

toml
loyiha = "Wisar"
versiya = "1.2.0"       # satr — qo'shtirnoq majburiy
port = 8000             # int
narx = 45000.50         # float
faol = true             # bool — faqat true/false
teglar = ["python", "web"]
sana = 2026-09-17       # native date

[baza]                  # jadval (table) = lug'at
host = "localhost"
port = 5432

[baza.pool]             # ichma-ich jadval
max = 10

[[servislar]]           # jadvallar massivi = lug'atlar ro'yxati
nom = "api"
[[servislar]]
nom = "worker"
python
import tomllib
with open("config.toml", "rb") as f:       # ⚠️ binar rejim
    malumot = tomllib.load(f)
malumot = tomllib.loads(matn)              # satrdan
TOML tuzilishi Python
[jadval] ichma-ich dict
[[massiv]] list[dict]
sana, vaqt date, datetime (native)
1_000_000 1000000 (pastki chiziq)

2.7. TOML xususiyatlari

Xususiyat Izoh
null yo'q TOML da bo'sh qiymat yo'q — kalitni umuman yozmang
Takroriy kalit TOMLDecodeError — YAML/JSON dan farqli, xato
Satr — faqat qo'shtirnoqda versiya = 1.2.0 xato; "1.2.0" to'g'ri
tomllib — faqat o'qish Yozish uchun tomli_w yoki tomlkit
tomllib.load — bytes Faylni "rb" rejimida oching
parse_float=Decimal JSON kabi aniqlik nazorati

TOML ning qat'iyligi — kuchli tomoni: xatolar konfiguratsiya yozilishida darhol topiladi, ishga tushganda emas.

2.8. Qaysi birini qachon

Format Eng yaxshi
TOML Loyiha sozlamasi, vosita konfiguratsiyasi (pyproject.toml), tekis-o'rtacha tuzilma
YAML Chuqur ichma-ich, ko'p qatorli (Kubernetes, CI/CD, Ansible) — lekin tuzoqlarga ehtiyot
JSON Mashinalararo almashinuv, API
.env Oddiy KALIT=qiymat sirlar

3. Tez ma'lumotnoma

python
import yaml, tomllib

malumot = yaml.safe_load(yaml_matn)                 # ⭐ safe_load
yaml.safe_dump(malumot, allow_unicode=True, sort_keys=False)

with open("config.toml", "rb") as f:                # ⚠️ binar
    sozlama = tomllib.load(f)
sozlama = tomllib.loads(toml_matn, parse_float=decimal.Decimal)

import tomli_w                                       # yozish (tashqi)
tomli_w.dump(malumot, open("out.toml", "wb"))

Qoidalar

YAML: har doim safe_load / safe_dump
YAML: yes/no/NO/1.10 — qo'shtirnoqqa oling
YAML: chekinish bo'shliq bilan, TAB emas
TOML: satr qo'shtirnoqda, faqat true/false
TOML: tomllib faqat o'qiydi, "rb" rejim
sozlama uchun: TOML (tekis), YAML (chuqur), JSON emas

4. Batafsil misollar

Misol 1 — YAML turlari va tuzoqlari

python
"""safe_load; turlar taxmini: yes/no/on/off, Norway problem, sexagesimal, versiya, date; qo'shtirnoq bilan yechim; blok skalyarlar (| va >)."""

import yaml

SOZLAMA = """
loyiha: Wisar
versiya: 1.10
faol: yes
debug: off
port: 8000
narx: 45000.50
teglar:
  - python
  - web
mamlakatlar: [NO, SE, FI]
vaqt_belgi: 22:22
sana: 2026-09-17
literal: |
  birinchi qator
  ikkinchi qator
folded: >
  bu uzun matn
  bitta qatorga birlashadi
"""


def main() -> None:
    d = yaml.safe_load(SOZLAMA)

    print("=== 1. ⚠️ Turlar taxmini ===")
    for kalit in ("versiya", "faol", "debug", "port", "narx", "sana"):
        print(f"  {kalit:9} = {d[kalit]!r:24} ({type(d[kalit]).__name__})")

    print("\n=== 2. ⚠️ Norway problem ===")
    print(f"  mamlakatlar: [NO, SE, FI] → {d['mamlakatlar']}")
    print(f"  ⚠️ NO (Norvegiya) → {d['mamlakatlar'][0]} (bool!), SE va FI — satr")

    print("\n=== 3. ⚠️ Boshqa tuzoqlar ===")
    print(f"  versiya 1.10 → {d['versiya']!r}  ← oxirgi nol yo'qoldi (float)")
    print(f"  22:22 → {d['vaqt_belgi']!r}  ← sexagesimal: 22×60+22")
    print(f"  yes → {d['faol']}, off → {d['debug']}  ← bool, satr emas")

    print("\n=== 4. ⭐ Yechim: qo'shtirnoq ===")
    toza = yaml.safe_load("""
    versiya: "1.10"
    mamlakatlar: ["NO", "SE", "FI"]
    faol: "yes"
    """)
    print(f"  versiya: {toza['versiya']!r} ({type(toza['versiya']).__name__})")
    print(f"  mamlakatlar: {toza['mamlakatlar']}")
    print(f"  faol: {toza['faol']!r} ({type(toza['faol']).__name__})")

    print("\n=== 5. Blok skalyarlar ===")
    print(f"  literal (|): {d['literal']!r}")
    print(f"  folded (>): {d['folded']!r}")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. ⚠️ Turlar taxmini ===
  versiya   = 1.1                      (float)
  faol      = True                     (bool)
  debug     = False                    (bool)
  port      = 8000                     (int)
  narx      = 45000.5                  (float)
  sana      = datetime.date(2026, 9, 17) (date)

=== 2. ⚠️ Norway problem ===
  mamlakatlar: [NO, SE, FI] → [False, 'SE', 'FI']
  ⚠️ NO (Norvegiya) → False (bool!), SE va FI — satr

=== 3. ⚠️ Boshqa tuzoqlar ===
  versiya 1.10 → 1.1  ← oxirgi nol yo'qoldi (float)
  22:22 → 1342  ← sexagesimal: 22×60+22
  yes → True, off → False  ← bool, satr emas

=== 4. ⭐ Yechim: qo'shtirnoq ===
  versiya: '1.10' (str)
  mamlakatlar: ['NO', 'SE', 'FI']
  faol: 'yes' (str)

=== 5. Blok skalyarlar ===
  literal (|): 'birinchi qator\nikkinchi qator\n'
  folded (>): 'bu uzun matn bitta qatorga birlashadi\n'

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

Misol 2 — YAML xavfsizlik, dump va anchor

python
"""safe_load xavfli tegni bloklaydi; safe_dump va allow_unicode; sort_keys; anchor, havola va merge (<<); ishonchsiz YAML da anchor kengayishi haqida eslatma."""

import yaml


def main() -> None:
    print("=== 1. ⚠️ safe_load xavfsizligi ===")
    xavfli = "!!python/object/apply:os.system ['echo hujum']"
    try:
        yaml.safe_load(xavfli)
    except yaml.YAMLError as xato:
        print(f"  safe_load bloklaydi: {type(xato).__name__}")
    print("  ⚠️ yaml.load(xavfli) esa buyruqni BAJARADI — hech qachon ishonchsizga yaml.load")

    print("\n=== 2. safe_dump ===")
    malumot = {"ism": "Oʻgʻiloy", "yosh": 25, "teglar": ["python", "web"], "faol": True}
    print("  allow_unicode=False (sukut) — ASCII escape:")
    for qator in yaml.safe_dump(malumot, sort_keys=True).splitlines():
        print(f"    {qator}")
    print("  ⭐ allow_unicode=True, sort_keys=False:")
    for qator in yaml.safe_dump(malumot, allow_unicode=True, sort_keys=False).splitlines():
        print(f"    {qator}")

    print("\n=== 3. Anchor va merge ===")
    konfig = """
    default: &sukut
      timeout: 30
      retry: 3
      log_level: info
    servis_api:
      <<: *sukut
      host: api.local
    servis_worker:
      <<: *sukut
      host: worker.local
      retry: 5
    """
    d = yaml.safe_load(konfig)
    print(f"  servis_api:    {d['servis_api']}")
    print(f"  servis_worker: {d['servis_worker']}  ← retry override qilindi")
    print("  ⚠️ anchor lar ichma-ich takrorlansa kengayadi — ishonchsiz YAML da DoS xavfi")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. ⚠️ safe_load xavfsizligi ===
  safe_load bloklaydi: ConstructorError
  ⚠️ yaml.load(xavfli) esa buyruqni BAJARADI — hech qachon ishonchsizga yaml.load

=== 2. safe_dump ===
  allow_unicode=False (sukut) — ASCII escape:
    faol: true
    ism: "O\u02BBg\u02BBiloy"
    teglar:
    - python
    - web
    yosh: 25
  ⭐ allow_unicode=True, sort_keys=False:
    ism: Oʻgʻiloy
    yosh: 25
    teglar:
    - python
    - web
    faol: true

=== 3. Anchor va merge ===
  servis_api:    {'timeout': 30, 'retry': 3, 'log_level': 'info', 'host': 'api.local'}
  servis_worker: {'timeout': 30, 'retry': 5, 'log_level': 'info', 'host': 'worker.local'}  ← retry override qilindi
  ⚠️ anchor lar ichma-ich takrorlansa kengayadi — ishonchsiz YAML da DoS xavfi

Nima ko'rsatdi: 2.4, 2.5-bo'limlar.

Misol 3 — TOML: qat'iy turlar va tuzilma

python
"""tomllib.loads/load; qat'iy turlar; native date/datetime; jadvallar va jadvallar massivi; pastki chiziqli sonlar; xatolar: takroriy kalit, null yo'q, satr qo'shtirnoqsiz; parse_float; tomli_w bilan yozish."""

import datetime
import io
import tomllib
from decimal import Decimal

import tomli_w

TOML = """# Wisar loyiha sozlamasi
loyiha = "Wisar"
versiya = "1.2.0"
port = 8000
narx = 45000.50
faol = true
katta = 1_000_000
teglar = ["python", "web"]
sana = 2026-09-17
vaqt = 2026-09-17T09:30:00+05:00

[baza]
host = "localhost"
port = 5432

[baza.pool]
min = 1
max = 10

[[servislar]]
nom = "api"
port = 8001

[[servislar]]
nom = "worker"
port = 8002
"""


def main() -> None:
    d = tomllib.loads(TOML)

    print("=== 1. ⭐ Qat'iy turlar ===")
    for kalit in ("versiya", "port", "narx", "faol", "katta"):
        print(f"  {kalit:8} = {d[kalit]!r:14} ({type(d[kalit]).__name__})")
    print(f"  ⭐ versiya '1.2.0' — satr bo'lib qoladi (YAML dan farqli)")

    print("\n=== 2. Native sana va vaqt ===")
    print(f"  sana: {d['sana']} ({type(d['sana']).__name__})")
    print(f"  vaqt: {d['vaqt']} mintaqa: {d['vaqt'].tzinfo}")

    print("\n=== 3. Jadvallar va massivlar ===")
    print(f"  baza: {d['baza']}")
    print(f"  baza.pool.max: {d['baza']['pool']['max']}")
    print(f"  servislar (jadvallar massivi): {[s['nom'] for s in d['servislar']]}")

    print("\n=== 4. ⚠️ Xatolar ===")
    for nom, matn in [("takroriy kalit", "a = 1\na = 2"), ("null yo'q", "a = null"),
                      ("qo'shtirnoqsiz satr", "versiya = 1.2.0")]:
        try:
            tomllib.loads(matn)
        except tomllib.TOMLDecodeError as xato:
            print(f"  {nom:20}: TOMLDecodeError: {str(xato).split(' (')[0]}")

    print("\n=== 5. parse_float va bytes ===")
    d2 = tomllib.loads("narx = 0.1", parse_float=Decimal)
    print(f"  parse_float=Decimal: {d2['narx']!r}")
    print(f"  tomllib.load bytes: {tomllib.load(io.BytesIO(b'x = 42'))['x']}")

    print("\n=== 6. tomli_w bilan yozish ===")
    yangi = {"loyiha": "Wisar", "port": 8000, "faol": True,
             "teglar": ["a", "b"], "baza": {"host": "localhost", "port": 5432}}
    chiqish = tomli_w.dumps(yangi)
    for qator in chiqish.splitlines():
        print(f"  {qator}")
    print(f"  aylanib qaytish teng: {tomllib.loads(chiqish) == yangi}")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. ⭐ Qat'iy turlar ===
  versiya  = '1.2.0'        (str)
  port     = 8000           (int)
  narx     = 45000.5        (float)
  faol     = True           (bool)
  katta    = 1000000        (int)
  ⭐ versiya '1.2.0' — satr bo'lib qoladi (YAML dan farqli)

=== 2. Native sana va vaqt ===
  sana: 2026-09-17 (date)
  vaqt: 2026-09-17 09:30:00+05:00 mintaqa: UTC+05:00

=== 3. Jadvallar va massivlar ===
  baza: {'host': 'localhost', 'port': 5432, 'pool': {'min': 1, 'max': 10}}
  baza.pool.max: 10
  servislar (jadvallar massivi): ['api', 'worker']

=== 4. ⚠️ Xatolar ===
  takroriy kalit      : TOMLDecodeError: Cannot overwrite a value
  null yo'q           : TOMLDecodeError: Invalid value
  qo'shtirnoqsiz satr : TOMLDecodeError: Expected newline or end of document after a statement

=== 5. parse_float va bytes ===
  parse_float=Decimal: Decimal('0.1')
  tomllib.load bytes: 42

=== 6. tomli_w bilan yozish ===
  loyiha = "Wisar"
  port = 8000
  faol = true
  teglar = [
      "a",
      "b",
  ]

  [baza]
  host = "localhost"
  port = 5432
  aylanib qaytish teng: True

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

Misol 4 — Amaliy: sozlamani yuklovchi va tekshiruvchi

Ilovamiz sozlamani TOML (asosiy) yoki YAML (muqobil) da qabul qiladi, uni sukut qiymatlar bilan ichma-ich birlashtiradi, sxema bo'yicha tekshiradi (turlar, majburiy maydonlar, oralik) va aniq xato beradi. Bu — YAML/TOML ni real ilovada to'g'ri ishlatish namunasi: format qat'iy o'qiladi, keyin qat'iy tekshiriladi.

python
"""TOML va YAML dan sozlama yuklash; ichma-ich birlashtirish; sxema tekshiruvi (tur, majburiylik, oraliq); format aniqlash; aniq xato xabarlari."""

import tomllib
from typing import Any

import yaml

SUKUT: dict[str, Any] = {
    "server": {"host": "0.0.0.0", "port": 8000, "workers": 4},
    "baza": {"host": "localhost", "port": 5432, "pool": {"min": 1, "max": 10}},
    "log": {"level": "info"},
}

# (yo'l, tur, tekshiruv)
SXEMA = [
    (("server", "port"), int, lambda v: 1 <= v <= 65535),
    (("server", "workers"), int, lambda v: 1 <= v <= 64),
    (("baza", "port"), int, lambda v: 1 <= v <= 65535),
    (("baza", "pool", "max"), int, lambda v: v >= 1),
    (("log", "level"), str, lambda v: v in {"debug", "info", "warning", "error"}),
]


def birlashtir(asos: dict, ustki: dict) -> dict:
    natija = {k: (v.copy() if isinstance(v, dict) else v) for k, v in asos.items()}
    for kalit, qiymat in ustki.items():
        if isinstance(qiymat, dict) and isinstance(natija.get(kalit), dict):
            natija[kalit] = birlashtir(natija[kalit], qiymat)
        else:
            natija[kalit] = qiymat
    return natija


def yukla(matn: str, format: str) -> dict:
    if format == "toml":
        return tomllib.loads(matn)
    if format == "yaml":
        d = yaml.safe_load(matn)
        if not isinstance(d, dict):
            raise ValueError("sozlama lug'at bo'lishi kerak")
        return d
    raise ValueError(f"noma'lum format: {format}")


def ol(d: dict, yol: tuple):
    for qism in yol:
        d = d[qism]
    return d


def tekshir(sozlama: dict) -> list[str]:
    xatolar = []
    for yol, tur, shart in SXEMA:
        nom = ".".join(yol)
        try:
            qiymat = ol(sozlama, yol)
        except (KeyError, TypeError):
            xatolar.append(f"{nom}: maydon yo'q")
            continue
        if isinstance(qiymat, bool) or not isinstance(qiymat, tur):
            xatolar.append(f"{nom}: {tur.__name__} kutilgan, {type(qiymat).__name__} keldi ({qiymat!r})")
        elif not shart(qiymat):
            xatolar.append(f"{nom}: qiymat oraliqdan tashqari ({qiymat!r})")
    return xatolar


def main() -> None:
    print("=== 1. TOML sozlama (qisman) ===")
    toml_matn = """
    [server]
    port = 9000
    workers = 8

    [baza]
    host = "db.example"

    [log]
    level = "debug"
    """
    sozlama = birlashtir(SUKUT, yukla(toml_matn, "toml"))
    print(f"  server: {sozlama['server']}")
    print(f"  baza:   {sozlama['baza']}  ← host o'zgardi, pool sukutdan")
    print(f"  log:    {sozlama['log']}")
    print(f"  tekshiruv: {tekshir(sozlama) or 'toza ✅'}")

    print("\n=== 2. Xatoli sozlama ===")
    yomon = """
    [server]
    port = 99999
    workers = "ko'p"

    [log]
    level = "trace"
    """
    sozlama = birlashtir(SUKUT, yukla(yomon, "toml"))
    for xato in tekshir(sozlama):
        print(f"  ❌ {xato}")

    print("\n=== 3. YAML muqobil (tuzoq bilan) ===")
    yaml_matn = """
    server:
      port: 8080
      workers: 4
    log:
      level: info
    faol: yes
    """
    d = yukla(yaml_matn, "yaml")
    sozlama = birlashtir(SUKUT, d)
    print(f"  server.port: {sozlama['server']['port']}")
    print(f"  ⚠️ 'faol: yes' → {sozlama['faol']!r} ({type(sozlama['faol']).__name__}) — YAML tuzog'i")
    print(f"  tekshiruv: {tekshir(sozlama) or 'toza ✅'}")

    print("\n=== 4. Xulosa ===")
    print("  TOML — qat'iy turlar, xato darhol; YAML — moslashuvchan, lekin tuzoqli")
    print("  ikkalasi ham: yuklashdan keyin sxema bilan tekshirish shart")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. TOML sozlama (qisman) ===
  server: {'host': '0.0.0.0', 'port': 9000, 'workers': 8}
  baza:   {'host': 'db.example', 'port': 5432, 'pool': {'min': 1, 'max': 10}}  ← host o'zgardi, pool sukutdan
  log:    {'level': 'debug'}
  tekshiruv: toza ✅

=== 2. Xatoli sozlama ===
  ❌ server.port: qiymat oraliqdan tashqari (99999)
  ❌ server.workers: int kutilgan, str keldi ("ko'p")
  ❌ log.level: qiymat oraliqdan tashqari ('trace')

=== 3. YAML muqobil (tuzoq bilan) ===
  server.port: 8080
  ⚠️ 'faol: yes' → True (bool) — YAML tuzog'i
  tekshiruv: toza ✅

=== 4. Xulosa ===
  TOML — qat'iy turlar, xato darhol; YAML — moslashuvchan, lekin tuzoqli
  ikkalasi ham: yuklashdan keyin sxema bilan tekshirish shart

Nima ko'rsatdi: 2.1, 2.6, 2.8-bo'limlar.


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

Noto'g'ri fikr To'g'risi
"YAML qiymatlarni satr qoldiradi" yes, NO, 1.10, 22:22 — bool/float/int ga aylanadi
"yaml.load xavfsiz" Kod bajaradi — safe_load ishlating
"TAB bilan chekinish mumkin" YAML da faqat bo'shliq
"TOML versiyani float qiladi" "1.2.0" — satr; TOML taxmin qilmaydi
"TOML da null bor" Yo'q — kalitni umuman yozmang
"Takroriy kalit — oxirgisi olinadi" TOML da TOMLDecodeError
"tomllib yoza oladi" Faqat o'qiydi; yozish — tomli_w
"YAML har doim TOML dan yaxshi" Chuqur tuzilma — YAML, tekis sozlama — TOML

6. Keng tarqalgan xatolar va yechimlari

1. yaml.load ishonchsiz ma'lumotga

python
yaml.load(tashqi)                                   # ❌ kod bajaradi
yaml.safe_load(tashqi)                              # ✅

2. Norway / yes-no tuzog'i

yaml
mamlakat: NO        # ❌ False
mamlakat: "NO"      # ✅ satr
enabled: yes        # ❌ True
enabled: "yes"      # ✅ (yoki: enabled: true — haqiqiy bool)

3. TOML faylni matn rejimida

python
tomllib.load(open("c.toml"))                        # ❌ TypeError (str keladi)
tomllib.load(open("c.toml", "rb"))                  # ✅ binar

4. TOML da qo'shtirnoqsiz satr

toml
versiya = 1.2.0     # ❌ TOMLDecodeError
versiya = "1.2.0"   # ✅

5. tomllib bilan yozishga urinish

python
tomllib.dumps(d)                                    # ❌ AttributeError
tomli_w.dumps(d)                                    # ✅

6. YAML da TAB

yaml
	kalit: qiymat   # ❌ TAB — ParserError
  kalit: qiymat     # ✅ bo'shliq

7. Sozlamani tekshirmasdan ishlatish

python
port = yaml.safe_load(matn)["port"]                 # ❌ tur/oraliq noma'lum
# ✅ yuklashdan keyin sxema tekshiruvi (Misol 4, yoki pydantic 13.8)

8. YAML dan Unicode ni escape bilan yozish

python
yaml.safe_dump(d)                                   # "Oʻ..." — o'qib bo'lmaydi
yaml.safe_dump(d, allow_unicode=True)               # ✅ Oʻgʻiloy

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 13.8-dars (o'tilgan): pydantic — sozlamani sxema bilan tekshirish (pydantic-settings)
  • 16.2-dars (o'tilgan): JSON — mashinalararo muqobil
  • 16.4-dars (o'tilgan): pickle/yaml.load — "ma'lumot bo'lgan kod" xavfi
  • 19-qism: paketlash — pyproject.toml
  • 20-qism: FastAPI — sozlama boshqaruvi
  • 28-qism: infratuzilma — Docker Compose, Kubernetes, CI/CD YAML

8. Eng yaxshi amaliyotlar

  1. YAML — har doim safe_load/safe_dump.

  2. YAML tuzoqli qiymatlarni (yes/NO/1.10) qo'shtirnoqqa oling.

  3. Loyiha/vosita sozlamasi — TOML; chuqur infratuzilma — YAML.

  4. TOML — satr qo'shtirnoqda, fayl "rb" rejimda.

  5. Format nima bo'lishidan qat'i nazar — yuklashdan keyin sxema bilan tekshiring.

  6. Sukut qiymatlar bilan ichma-ich birlashtiring.

  7. YAML da chekinish — bo'shliq, hech qachon TAB.

  8. Sirlar — sozlama faylida emas, muhit o'zgaruvchisi yoki maxfiy boshqaruvda.


9. Amaliy topshiriq

Vazifa 1: Natijani bashorat qiling

python
import yaml, tomllib
1.  print(yaml.safe_load("x: yes")["x"])
2.  print(yaml.safe_load("x: NO")["x"])
3.  print(yaml.safe_load("x: 1.10")["x"])
4.  print(yaml.safe_load('x: "yes"')["x"])
5.  print(type(yaml.safe_load("x: 2026-09-17")["x"]).__name__)
6.  print(yaml.safe_load("x: 22:22")["x"])
7.  print(tomllib.loads('x = "1.2.0"')["x"])
8.  print(type(tomllib.loads("x = 2026-09-17")["x"]).__name__)
9.  print(tomllib.loads("x = 1_000")["x"])
10. print(tomllib.loads("[a]\nb = 1")["a"]["b"])
11. try:
        tomllib.loads("a = 1\na = 2")
    except tomllib.TOMLDecodeError:
        print("xato")
12. print(yaml.safe_load("a: [1, 2]\nb: {x: 1}"))
Javoblar
  1. True
  2. False
  3. 1.1
  4. yes
  5. date
  6. 1342
  7. 1.2.0
  8. date
  9. 1000
  10. 1
  11. xato
  12. {'a': [1, 2], 'b': {'x': 1}}

Vazifa 2: Xatolarni tuzating

python
1.  def yukla(matn):
        return yaml.load(matn)                      # foydalanuvchi yuborgan

2.  def toml_oqi(yol):
        with open(yol) as f:
            return tomllib.load(f)

3.  # config.yaml:
    #   mamlakatlar: [NO, US, GB]
    #   versiya: 2.10
    def oqi(yaml_matn):
        d = yaml.safe_load(yaml_matn)
        return d["mamlakatlar"], d["versiya"]       # NO va 2.10 kutilgan

4.  def saqla(yol, sozlama):
        with open(yol, "w") as f:
            tomllib.dump(sozlama, f)

5.  def dump_yaml(malumot):
        return yaml.safe_dump(malumot)              # o'zbekcha matn bor
Javoblar
python
1.  def yukla(matn):
        return yaml.safe_load(matn)                 # kod bajarilmaydi

2.  def toml_oqi(yol):
        with open(yol, "rb") as f:                  # binar
            return tomllib.load(f)

3.  # YAML faylida tuzoqli qiymatlar qo'shtirnoqda bo'lishi kerak:
    #   mamlakatlar: ["NO", "US", "GB"]
    #   versiya: "2.10"
    def oqi(yaml_matn):
        d = yaml.safe_load(yaml_matn)
        return d["mamlakatlar"], d["versiya"]

4.  import tomli_w
    def saqla(yol, sozlama):
        with open(yol, "wb") as f:                  # tomli_w, binar
            tomli_w.dump(sozlama, f)

5.  def dump_yaml(malumot):
        return yaml.safe_dump(malumot, allow_unicode=True, sort_keys=False)

Vazifa 3: Format konvertori

konvert kirish.yaml chiqish.toml:

  1. YAML ↔ TOML ↔ JSON o'zaro (kengaytmadan format aniqlash)
  2. TOML da null yo'qligini hisobga oling: None maydonlarni tushiring va ogohlantiring
  3. YAML tuzoqlarini aniqlab ogohlantiring (NO, yes, 1.10 kabi qiymatlar)
  4. Aylanib qaytish testi: YAML → TOML → YAML semantik teng

Vazifa 4: pyproject.toml o'quvchi

  1. [project] dan name, version, dependencies ni ajrating
  2. [tool.*] bo'limlarini ro'yxatlang
  3. Bog'liqlik spetsifikatsiyalarini (paket>=1.0) tahlil qiling
  4. Yo'q yoki noto'g'ri maydonlarni qator:ustun bilan xabar qiling (TOMLDecodeError)

Vazifa 5: YAML tuzoq detektori

yaml_tekshir(matn) — quyidagilarni ogohlantirsin:

  1. Qo'shtirnoqsiz yes/no/on/off/NO va shunga o'xshash qiymatlar
  2. Oxirgi nolli versiya (1.10), sexagesimal (22:22)
  3. TAB bilan chekinish
  4. Har biriga qator raqami va tuzatilgan variant

Vazifa 6: Sozlama qatlamlari

  1. Uch qatlam: sukut (kod) → config.toml → muhit o'zgaruvchilari
  2. Har qatlam oldingisini ichma-ich bekor qilsin (Misol 4 dagi birlashtir)
  3. WISAR_SERVER__PORT=9000 kabi o'zgaruvchilar ichma-ich yo'lga aylansin
  4. Yakuniy sozlamani sxema bilan tekshiring (pydantic bilan solishtiring)

Vazifa 7: O'ylash

YAML "odam uchun eng qulay" format sifatida yaratildi, lekin bugun uni "1.5 milliard dollarlik xato" (Norway problem va boshqalar) deb tanqid qiladilar. TOML esa aynan YAML muammolariga javob sifatida yaratildi va Python pyproject.toml uchun uni tanladi. Nima uchun "qulaylik" murakkablik va tuzoqlar keltiradi, va TOML ning "zerikarli aniqligi" nega sozlama uchun afzallik?

Javob

Qisqa javob: YAML ning tuzoqlari "qulaylik" ning to'g'ridan-to'g'ri natijasi: qo'shtirnoqsiz yozishga ruxsat berish uchun YAML turni taxmin qilishi kerak, va har qanday taxmin ba'zan yanglishadi (NO → False). TOML aksincha — biroz ko'proq yozishni (qo'shtirnoq) talab qiladi, lekin hech narsani taxmin qilmaydi, shuning uchun tuzoqsiz. Sozlama fayllari kamdan-kam yoziladi, lekin ko'p o'qiladi va xatosi qimmatga tushadi — bu yerda "zerikarli aniqlik" xavfsizlikdan ustun.

1. Nega qulaylik murakkablik keltiradi

YAML qulayligi Narxi
Qo'shtirnoqsiz qiymat Tur taxmini kerak → yanglish
yes/no bool NO, mamlakat kodi bilan to'qnashadi
Chekinish tuzilma TAB/bo'shliq, ko'rinmas xatolar
Anchor, merge, tag Katta spetsifikatsiya, !!python xavfi
Ko'p yozish usuli Bir narsani turlicha yozish mumkin

2. Nega TOML "zerikarli aniqlik" afzal

TOML tanlovi Foyda
Satr — majburiy qo'shtirnoq Taxmin yo'q, tuzoq yo'q
Faqat true/false yes/NO chalkashligi yo'q
Takroriy kalit — xato Jim xato yo'q
Kichik, aniq grammatika Bir xil talqin
Native sana, son Aniq turlar

3. Sozlama fayli konteksti

Xususiyat Ta'siri
Kam yoziladi Qo'shtirnoqning "noqulayligi" arzimas
Ko'p o'qiladi/yuklanadi Aniqlik va bir xillik muhim
Xatosi qimmat Ishlab chiqarishda buzilgan sozlama — jiddiy nosozlik
Odam va vosita o'qiydi Ikkovi bir xil tushunishi kerak

4. Har birining o'rni

Format Eng mos
TOML Tekis/o'rtacha sozlama, vositalar (pyproject.toml)
YAML Chuqur ichma-ich, ko'p qatorli (Kubernetes) — lekin qat'iy amaliyot bilan
JSON Almashinuv, API

5. Muhandislik saboqlari

  1. "Qulaylik" ko'pincha "kamroq belgi" degani — lekin belgi ma'no tashiydi
  2. Taxmin (implicit) qulay ko'rinadi, lekin chegara holatlarida yanglishadi
  3. Aniqlik (explicit) zerikarli, lekin ishonchli — kritik konfiguratsiyada afzal
  4. Format vazifaga mos bo'lsin; YAML ishlatilsa — tuzoqli qiymatlarni qo'shtirnoqda va qat'iy tekshiruv bilan

6. Xulosa

  1. YAML tuzoqlari — turni taxmin qilish zaruratidan
  2. TOML aniqligi — taxminni yo'q qiladi
  3. Sozlama uchun ishonchlilik qulaylikdan muhim
  4. TOML tekis sozlama, YAML chuqur tuzilma; ikkovida ham sxema tekshiruvi

Nimani mustahkamlaydi: 2.1–2.8-bo'limlar.


Xulosa

Bu darsda odam yozadigan ikki sozlama formatini — YAML va TOML ni o'rgandik.

Eng muhim uch fikr:

  1. YAML "qulay", lekin turni taxmin qiladi. yes/on/true → True, NO → False (Norway problem), 1.10 → 1.1, 22:22 → 1342, 2026-09-17 → date. Yechim — tuzoqli qiymatlarni qo'shtirnoqqa olish. Va har doim safe_load/safe_dump: oddiy yaml.load !!python/object teglari orqali pickle kabi kod bajaradi. Chiqishda allow_unicode=True, chekinish faqat bo'shliq bilan.

  2. TOML — qat'iy va aniq. Satr qo'shtirnoqda, faqat true/false, null yo'q, takroriy kalit xato, native sana va son. [jadval] ichma-ich lug'at, [[massiv]] lug'atlar ro'yxati. tomllib (3.11+ stdlib) faqat o'qiydi va faylni "rb" rejimda oladi; yozish uchun tomli_w. Qat'iyligi tufayli xatolar sozlama yozilishida, ishga tushganda emas, topiladi.

  3. Format nima bo'lishidan qat'i nazar — tekshirish shart. Sozlamani yuklash — birinchi qadam; ikkinchisi — sukut qiymatlar bilan ichma-ich birlashtirish va sxema bo'yicha (turlar, majburiylik, oraliq) tekshirish. TOML — tekis loyiha sozlamasi (pyproject.toml), YAML — chuqur infratuzilma (Kubernetes, CI/CD), JSON — mashinalararo almashinuv; sirlar esa hech qachon sozlama faylida emas.

Keyingi darsda ma'lumotni saqlashning kuchli usulini — o'rnatilgan sqlite3 bazasini o'rganamiz: SQL asoslari, parametrli so'rovlar (SQL injection dan himoya), tranzaksiyalar va Python obyektlarini jadvalga bog'lash.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
16.6-dars: YAML va TOML — IlmHamroh