Loyiha: to'liq ko'rinish
Nima qurdik
Birinchi bobda 9 qatorli skript bor edi va u birinchi buzuq qatorda yiqildi. Endi to'liq loyiha bor.
find src tests -name "*.py" | sort echo "" echo "--- konfiguratsiya fayllari ---" ls -1 pyproject.toml ruff.toml mypy.ini .gitignore .env.namuna tekshir.sh 2>/dev/null
src/hisobot/__init__.py src/hisobot/__main__.py src/hisobot/chiqarish.py src/hisobot/cli.py src/hisobot/hisob.py src/hisobot/ko_p.py src/hisobot/modellar.py src/hisobot/muhit.py src/hisobot/oqish.py src/hisobot/sozlama.py src/hisobot/tarmoq.py src/hisobot/tekshiruv.py src/hisobot/xatolar.py tests/conftest.py tests/test_chiqarish.py tests/test_cli.py tests/test_hisob.py tests/test_izolyatsiya.py tests/test_jurnal.py tests/test_ko_p.py tests/test_oqish.py tests/test_sana.py tests/test_scope.py tests/test_sozlama.py tests/test_tarmoq.py tests/test_tekshiruv.py tests/test_xatolar.py --- konfiguratsiya fayllari --- .env.namuna .gitignore mypy.ini pyproject.toml ruff.toml tekshir.sh
Har bob nimani qo'shganini ko'rib chiqamiz:
import pandas as pd show(pd.DataFrame([ {"bob": 1, "qo'shgan narsasi": "To'rt ishni ajratish: o'qish, tekshirish, hisoblash, ko'rsatish"}, {"bob": 2, "qo'shgan narsasi": "venv, pyproject.toml, src/ tartibi, tahrirlanadigan o'rnatish"}, {"bob": 3, "qo'shgan narsasi": "Paket tuzilishi, `python3 -m hisobot`, __init__.py"}, {"bob": 4, "qo'shgan narsasi": "Talaba/Natija dataclass lari, Daraja enum i"}, {"bob": 5, "qo'shgan narsasi": "Tur ko'rsatkichlari, mypy strict"}, {"bob": 6, "qo'shgan narsasi": "Birinchi testlar, TDD bilan sanani_tekshir"}, {"bob": 7, "qo'shgan narsasi": "parametrize, fixture, conftest.py, qamrov"}, {"bob": 8, "qo'shgan narsasi": "Istisno oilasi, to'plash vs otish, tushunarli xabarlar"}, {"bob": 9, "qo'shgan narsasi": "logging, -v/-vv darajalari"}, {"bob": 10, "qo'shgan narsasi": "chiqarish.py: JSON va CSV yozish"}, {"bob": 11, "qo'shgan narsasi": "Sozlama muhit o'zgaruvchilaridan, .env, sirlar"}, {"bob": 12, "qo'shgan narsasi": "tarmoq.py: timeout, qayta urinish, backoff"}, {"bob": 13, "qo'shgan narsasi": "ko_p.py: bir nechta faylni parallel qayta ishlash"}, {"bob": 14, "qo'shgan narsasi": "Profiling, kesh, generator bilan xotira tejash"}, {"bob": 15, "qo'shgan narsasi": "cli.py: to'liq argparse, qaytish kodlari, o'rnatiladigan buyruq"}, {"bob": 16, "qo'shgan narsasi": "ruff, tekshir.sh, CI, pre-commit"}, ]))
| bob | qo'shgan narsasi |
|---|---|
| 1 | To'rt ishni ajratish: o'qish, tekshirish, hisoblash, ko'rsatish |
| 2 | venv, pyproject.toml, src/ tartibi, tahrirlanadigan o'rnatish |
| 3 | Paket tuzilishi, `python3 -m hisobot`, __init__.py |
| 4 | Talaba/Natija dataclass lari, Daraja enum i |
| 5 | Tur ko'rsatkichlari, mypy strict |
| 6 | Birinchi testlar, TDD bilan sanani_tekshir |
| 7 | parametrize, fixture, conftest.py, qamrov |
| 8 | Istisno oilasi, to'plash vs otish, tushunarli xabarlar |
| 9 | logging, -v/-vv darajalari |
| 10 | chiqarish.py: JSON va CSV yozish |
| 11 | Sozlama muhit o'zgaruvchilaridan, .env, sirlar |
| 12 | tarmoq.py: timeout, qayta urinish, backoff |
| 13 | ko_p.py: bir nechta faylni parallel qayta ishlash |
| 14 | Profiling, kesh, generator bilan xotira tejash |
| 15 | cli.py: to'liq argparse, qaytish kodlari, o'rnatiladigan buyruq |
… 16 qatordan birinchi 15 tasi
Oxirgi bo'lak: hisobot matni
Bitta narsa yetishmayapti — odam o'qiydigan hisobot. Uni qo'shamiz.
shu faylni yaratingsrc/hisobot/matn.py
"""Odam o'qiydigan hisobot matni.""" from .hisob import daraja_taqsimoti, eng_yaxshi, guruh_ortachasi from .modellar import Natija def hisobot_matni(natija: Natija, kenglik: int = 46) -> str: """Natijadan formatlangan matnli hisobot yasaydi.""" chiziq = "=" * kenglik qatorlar = [chiziq, "TALABALAR HISOBOTI".center(kenglik), chiziq, ""] jami = natija.jami ulush = 100 * len(natija.talabalar) / jami if jami else 0.0 qatorlar.append(f"Jami qator : {jami}") qatorlar.append(f"To'g'ri : {len(natija.talabalar)} ({ulush:.1f}%)") qatorlar.append(f"Rad etilgan : {len(natija.xatolar)}") if natija.talabalar: qatorlar += ["", "-" * kenglik, "GURUH BO'YICHA O'RTACHA", "-" * kenglik] ortachalar = guruh_ortachasi(natija.talabalar) eng_katta = max(ortachalar.values()) for guruh, ortacha in ortachalar.items(): ustun = "#" * int(20 * ortacha / eng_katta) if eng_katta else "" qatorlar.append(f" {guruh:<4} {ortacha:6.2f} {ustun}") qatorlar += ["", "-" * kenglik, "DARAJALAR", "-" * kenglik] for daraja, soni in daraja_taqsimoti(natija.talabalar).items(): foiz = 100 * soni / len(natija.talabalar) qatorlar.append(f" {daraja:<12} {soni:3} ({foiz:5.1f}%)") eng = eng_yaxshi(natija.talabalar) if eng is not None: qatorlar += ["", f"Eng yuqori: {eng.ism} — {eng.baho} ({eng.guruh} guruhi)"] if natija.xatolar: qatorlar += ["", "-" * kenglik, f"XATOLAR ({len(natija.xatolar)})", "-" * kenglik] for qator, ism, sabab in natija.xatolar[:10]: qatorlar.append(f" {qator:>4}-qator {ism:<12} {sabab}") if len(natija.xatolar) > 10: qatorlar.append(f" ... va yana {len(natija.xatolar) - 10} ta") qatorlar += ["", chiziq] return "\n".join(qatorlar)
shu faylni yaratingsrc/hisobot/__init__.py
"""CSV ma'lumotini tekshirib hisobot chiqaradigan asbob.""" from .chiqarish import csv_yoz, json_yoz, xulosa from .hisob import daraja_taqsimoti, eng_yaxshi, guruh_ortachasi from .matn import hisobot_matni from .modellar import Daraja, Natija, Talaba from .oqish import oqi, tozala from .sozlama import Sozlama from .tekshiruv import bahoni_tekshir, sanani_tekshir from .xatolar import FaylXato, HisobotXato, QatorXato, SozlamaXato __version__ = "1.0.0" __all__ = [ "Daraja", "FaylXato", "HisobotXato", "Natija", "QatorXato", "Sozlama", "SozlamaXato", "Talaba", "__version__", "bahoni_tekshir", "csv_yoz", "daraja_taqsimoti", "eng_yaxshi", "guruh_ortachasi", "hisobot_matni", "json_yoz", "oqi", "sanani_tekshir", "tozala", "xulosa", ]
CLI ni yangi funksiyaga ulaymiz:
shu faylni yaratingsrc/hisobot/cli.py
"""Buyruq qatori interfeysi.""" import argparse import json import logging import sys from collections.abc import Mapping from pathlib import Path from . import __version__ from .chiqarish import csv_yoz, json_yoz, xulosa from .ko_p import hammasi from .matn import hisobot_matni from .modellar import Natija from .sozlama import Sozlama from .xatolar import SozlamaXato log = logging.getLogger(__name__) def jurnalni_sozla(batafsil: int, jim: bool) -> None: daraja = logging.ERROR if jim else {0: logging.WARNING, 1: logging.INFO}.get( batafsil, logging.DEBUG) logging.basicConfig(level=daraja, stream=sys.stderr, format="%(levelname)-8s %(name)s: %(message)s") def tahlilchi() -> argparse.ArgumentParser: p = argparse.ArgumentParser( prog="hisobot", description="CSV fayldan talabalar hisobotini tayyorlaydi.", epilog="Misol: hisobot talabalar.csv --format json --chiqish natija.json", ) p.add_argument("fayllar", nargs="+", type=Path, metavar="FAYL") p.add_argument("--format", choices=["matn", "json", "csv"], default="matn") p.add_argument("--chiqish", type=Path, metavar="YO'L") p.add_argument("--max-baho", type=int, metavar="N") p.add_argument("--qatiy", action="store_true") p.add_argument("-j", "--ishchilar", type=int, default=4, metavar="N") p.add_argument("-v", "--batafsil", action="count", default=0) p.add_argument("-q", "--jim", action="store_true") p.add_argument("--version", action="version", version=f"hisobot {__version__}") return p def _sozlamani_tayyorla(args: argparse.Namespace) -> Sozlama: s = Sozlama.muhitdan() if args.max_baho is None and not args.qatiy: return s s = Sozlama(max_baho=args.max_baho if args.max_baho is not None else s.max_baho, min_baho=s.min_baho, chiqish_papka=s.chiqish_papka, qatiy=args.qatiy or s.qatiy) s.tekshir() return s def _birlashtir(natijalar: Mapping[str, Natija | str]) -> tuple[Natija | None, bool]: birlashgan: Natija | None = None xatolar_bor = False for nom in sorted(natijalar): n = natijalar[nom] if not isinstance(n, Natija): log.error("%s: %s", nom, n) xatolar_bor = True continue if birlashgan is None: birlashgan = Natija(talabalar=list(n.talabalar), xatolar=list(n.xatolar)) else: birlashgan.talabalar.extend(n.talabalar) birlashgan.xatolar.extend(n.xatolar) return birlashgan, xatolar_bor def main(argv: list[str] | None = None) -> int: args = tahlilchi().parse_args(argv) jurnalni_sozla(args.batafsil, args.jim) try: sozlama = _sozlamani_tayyorla(args) except SozlamaXato as e: log.error("sozlama xatosi: %s", e) return 2 birlashgan, xatolar_bor = _birlashtir( hammasi(list(args.fayllar), ishchilar=args.ishchilar, sozlama=sozlama) ) if birlashgan is None: log.error("hech qaysi fayl o'qilmadi") return 1 if birlashgan.xatolar: xatolar_bor = True if sozlama.qatiy: log.error("qat'iy rejim: %d xato qator topildi", len(birlashgan.xatolar)) return 1 if args.format == "json": if args.chiqish: json_yoz(birlashgan, args.chiqish) else: print(json.dumps(xulosa(birlashgan), ensure_ascii=False, indent=2)) elif args.format == "csv": if not args.chiqish: log.error("--format csv uchun --chiqish kerak") return 2 csv_yoz(birlashgan, args.chiqish) else: matn = hisobot_matni(birlashgan) if args.chiqish: args.chiqish.write_text(matn + "\n", encoding="utf-8") log.info("hisobot yozildi: %s", args.chiqish) else: print(matn) return 1 if xatolar_bor else 0 if __name__ == "__main__": sys.exit(main())
.venv/bin/python3 -m pip install --quiet -e . .venv/bin/hisobot sinov_malumot.csv --jim
==============================================
TALABALAR HISOBOTI
==============================================
Jami qator : 8
To'g'ri : 6 (75.0%)
Rad etilgan : 2
----------------------------------------------
GURUH BO'YICHA O'RTACHA
----------------------------------------------
A 90.67 ####################
B 83.00 ##################
C 61.00 #############
----------------------------------------------
DARAJALAR
----------------------------------------------
yaxshi 3 ( 50.0%)
a'lo 2 ( 33.3%)
qoniqarli 1 ( 16.7%)
Eng yuqori: Feruza — 95 (A guruhi)
----------------------------------------------
XATOLAR (2)
----------------------------------------------
5-qator Elyor baho son emas: ''
8-qator Hasan baho son emas: 'abc'
==============================================
Chiqish formati o'zgardi — demak 15-bobdagi testlar ham yangilanishi kerak. 8-bobdagi bilan bir xil holat: xulq ongli o'zgardi, test unga ergashadi.
.venv/bin/python3 -m pytest tests/test_cli.py -q 2>&1 | tail -6
E + where readouterr = <_pytest.capture.CaptureFixture object at 0x7fb028126590>.readouterr tests/test_cli.py:60: AssertionError =========================== short test summary info ============================ FAILED tests/test_cli.py::test_toza_fayl_nol_qaytaradi - assert "to'g'ri: 2" ... FAILED tests/test_cli.py::test_bir_nechta_fayl - assert 'jami: 4' in "=======...
shu faylni yaratingtests/test_cli.py
import json import pytest from hisobot.cli import main TOGRI = "ism,guruh,baho,sana\nAziz,A,85,2026-09-01\nBobur,B,95,2026-09-02\n" XATOLI = "ism,guruh,baho,sana\nAziz,A,abc,2026-09-01\n" def _fayl(papka, nom, matn): y = papka / nom y.write_text(matn, encoding="utf-8") return str(y) def test_toza_fayl_nol_qaytaradi(tmp_path, capsys): kod = main([_fayl(tmp_path, "a.csv", TOGRI), "--jim"]) assert kod == 0 chiqish = capsys.readouterr().out assert "To'g'ri : 2" in chiqish assert "TALABALAR HISOBOTI" in chiqish def test_xatoli_fayl_bir_qaytaradi(tmp_path): assert main([_fayl(tmp_path, "b.csv", XATOLI), "--jim"]) == 1 def test_fayl_yoq_bir_qaytaradi(tmp_path): assert main([str(tmp_path / "yoq.csv"), "--jim"]) == 1 def test_json_format(tmp_path, capsys): main([_fayl(tmp_path, "c.csv", TOGRI), "--format", "json", "--jim"]) malumot = json.loads(capsys.readouterr().out) assert malumot["togri"] == 2 assert malumot["guruh_ortachasi"] == {"A": 85.0, "B": 95.0} def test_json_faylga(tmp_path): chiqish = tmp_path / "n.json" main([_fayl(tmp_path, "d.csv", TOGRI), "--format", "json", "--chiqish", str(chiqish), "--jim"]) assert json.loads(chiqish.read_text(encoding="utf-8"))["togri"] == 2 def test_matn_faylga(tmp_path): """Yangi xulq: --format matn ham faylga yozila oladi.""" chiqish = tmp_path / "n.txt" main([_fayl(tmp_path, "d2.csv", TOGRI), "--chiqish", str(chiqish), "--jim"]) assert "TALABALAR HISOBOTI" in chiqish.read_text(encoding="utf-8") def test_csv_chiqishsiz_ikki_qaytaradi(tmp_path): assert main([_fayl(tmp_path, "e.csv", TOGRI), "--format", "csv", "--jim"]) == 2 def test_max_baho_cheklovi(tmp_path): """85 va 95 — 5 balli tizimda ikkalasi ham xato.""" assert main([_fayl(tmp_path, "f.csv", TOGRI), "--max-baho", "5", "--jim"]) == 1 def test_notogri_max_baho(tmp_path): assert main([_fayl(tmp_path, "g.csv", TOGRI), "--max-baho", "-5", "--jim"]) == 2 def test_bir_nechta_fayl(tmp_path, capsys): kod = main([_fayl(tmp_path, "h1.csv", TOGRI), _fayl(tmp_path, "h2.csv", TOGRI), "--jim"]) assert kod == 0 assert "Jami qator : 4" in capsys.readouterr().out def test_notogri_argument_sistemexit(tmp_path): with pytest.raises(SystemExit) as e: main([_fayl(tmp_path, "i.csv", TOGRI), "--format", "xml"]) assert e.value.code == 2
.venv/bin/python3 -m pytest tests/test_cli.py -q
........... [100%]
Katta ma'lumotda sinaymiz
.venv/bin/python3 -c " import csv, random random.seed(7) guruhlar = ['A', 'B', 'C', 'D'] with open('katta_sinov.csv', 'w', encoding='utf-8', newline='') as f: w = csv.writer(f) w.writerow(['ism', 'guruh', 'baho', 'sana']) for i in range(5000): baho = random.choice([str(random.randint(40, 100))] * 18 + ['abc', '', '150']) sana = random.choice(['2026-09-01'] * 19 + ['01.09.2026']) w.writerow([f'Talaba{i:04d}', random.choice(guruhlar), baho, sana]) print('yasaldi: katta_sinov.csv') " wc -l katta_sinov.csv
yasaldi: katta_sinov.csv 5001 katta_sinov.csv
time .venv/bin/hisobot katta_sinov.csv --jim
==============================================
TALABALAR HISOBOTI
==============================================
Jami qator : 5000
To'g'ri : 4107 (82.1%)
Rad etilgan : 893
----------------------------------------------
GURUH BO'YICHA O'RTACHA
----------------------------------------------
A 69.78 ###################
B 69.22 ###################
C 69.98 ####################
D 69.49 ###################
----------------------------------------------
DARAJALAR
----------------------------------------------
qoniqarsiz 1381 ( 33.6%)
qoniqarli 1049 ( 25.5%)
yaxshi 962 ( 23.4%)
a'lo 715 ( 17.4%)
Eng yuqori: Talaba0024 — 100 (A guruhi)
----------------------------------------------
XATOLAR (893)
----------------------------------------------
7-qator Talaba0005 baho son emas: 'abc'
8-qator Talaba0006 baho 0..100 oralig'ida bo'lishi kerak, berilgan: 150
9-qator Talaba0007 baho son emas: 'abc'
13-qator Talaba0011 baho son emas: 'abc'
15-qator Talaba0013 sana formati noto'g'ri (YYYY-MM-DD kutilgan): '01.09.2026'
17-qator Talaba0015 baho son emas: 'abc'
19-qator Talaba0017 baho son emas: 'abc'
24-qator Talaba0022 sana formati noto'g'ri (YYYY-MM-DD kutilgan): '01.09.2026'
38-qator Talaba0036 baho son emas: 'abc'
40-qator Talaba0038 sana formati noto'g'ri (YYYY-MM-DD kutilgan): '01.09.2026'
... va yana 883 ta
==============================================
real 0m0.267s
user 0m0.035s
sys 0m0.012s
5000 qator, jumladan ataylab buzilganlari. Dastur hammasini qayta ishladi, xatolarni sanadi va hisobot berdi.
Barcha formatlar
echo "=== JSON ===" .venv/bin/hisobot katta_sinov.csv --format json --chiqish natija.json --jim head -14 natija.json echo "" echo "=== CSV (birinchi 3 qator) ===" .venv/bin/hisobot katta_sinov.csv --format csv --chiqish natija.csv --jim head -3 natija.csv wc -l natija.csv rm -f natija.csv natija.json
=== JSON ===
{
"jami": 5000,
"togri": 4107,
"xato": 893,
"guruh_ortachasi": {
"A": 69.78,
"B": 69.22,
"C": 69.98,
"D": 69.49
},
"darajalar": {
"qoniqarsiz": 1381,
"qoniqarli": 1049,
"yaxshi": 962,
=== CSV (birinchi 3 qator) ===
ism,guruh,baho,sana,daraja
Talaba0000,A,60,2026-09-01,qoniqarli
Talaba0001,C,44,2026-09-01,qoniqarsiz
4108 natija.csv
Yakuniy sifat tekshiruvi
Bu bobda yangi kod yozdik (matn.py, yangilangan cli.py), shuning uchun avval uni formatlaymiz —
16-bobdagi qoida bo'yicha:
ruff format src tests ruff check --fix src tests
2 files reformatted, 26 files left unchanged All checks passed!
./tekshir.sh
=== format === 28 files already formatted OK === linter === All checks passed! OK === turlar === Success: no issues found in 14 source files OK === testlar === ........................................................................ [ 85%] ............ [100%] OK HAMMASI O'TDI
.venv/bin/python3 -m pytest --cov=hisobot --cov-report=term-missing -q 2>&1 | tail -20
_______________ coverage: platform linux, python 3.10.12-final-0 _______________ Name Stmts Miss Cover Missing -------------------------------------------------------- src/hisobot/__init__.py 10 0 100% src/hisobot/__main__.py 2 2 0% 3-5 src/hisobot/chiqarish.py 22 0 100% src/hisobot/cli.py 82 3 96% 98-99, 110 src/hisobot/hisob.py 12 0 100% src/hisobot/ko_p.py 22 0 100% src/hisobot/matn.py 32 1 97% 40 src/hisobot/modellar.py 33 1 97% 21 src/hisobot/muhit.py 17 17 0% 3-26 src/hisobot/oqish.py 42 4 90% 25-28 src/hisobot/sozlama.py 39 1 97% 59 src/hisobot/tarmoq.py 30 4 87% 41-44 src/hisobot/tekshiruv.py 22 0 100% src/hisobot/xatolar.py 13 4 69% 24-27 -------------------------------------------------------- TOTAL 378 37 90%
Loyiha raqamlarda
import subprocess, sys from pathlib import Path ish = ISH src = list((ish / "src").rglob("*.py")) testlar = list((ish / "tests").rglob("*.py")) def qatorlar(fayllar): return sum(len(p.read_text(encoding="utf-8").splitlines()) for p in fayllar) import pandas as pd show(pd.DataFrame([ {"o'lchov": "Manba fayllari", "qiymat": len(src)}, {"o'lchov": "Manba qatorlari", "qiymat": qatorlar(src)}, {"o'lchov": "Test fayllari", "qiymat": len(testlar)}, {"o'lchov": "Test qatorlari", "qiymat": qatorlar(testlar)}, {"o'lchov": "Test / manba nisbati", "qiymat": f"{qatorlar(testlar) / max(qatorlar(src), 1):.2f}"}, {"o'lchov": "Eng katta fayl, qator", "qiymat": max(len(p.read_text(encoding='utf-8').splitlines()) for p in src)}, ])) print("\nmodullar va vazifalari:") for p in sorted(src): if p.name == "__init__.py": continue birinchi = p.read_text(encoding="utf-8").splitlines()[0].strip('"') print(f" {p.name:16} {birinchi[:58]}")
modullar va vazifalari: __main__.py python3 -m hisobot bilan ishga tushadi. chiqarish.py Natijani turli formatlarda yozish. cli.py Buyruq qatori interfeysi. hisob.py Statistika: kiritish/chiqarishsiz, faqat hisob. ko_p.py Bir nechta CSV faylni parallel qayta ishlash. matn.py Odam o'qiydigan hisobot matni. modellar.py Ma'lumot tuzilmalari. muhit.py Ixtiyoriy .env faylini o'qish. Faqat lokal qulaylik uchun. oqish.py CSV o'qish va qatorlarni tekshirib modelga aylantirish. sozlama.py Konfiguratsiya: muhit o'zgaruvchilaridan o'qiladi, sukut q tarmoq.py HTTP so'rovlari: timeout, qayta urinish, backoff. tekshiruv.py Qoidalar: qator to'g'rimi yoki yo'q. xatolar.py Loyihaning istisno oilasi.
| o'lchov | qiymat |
|---|---|
| Manba fayllari | 14 |
| Manba qatorlari | 620 |
| Test fayllari | 14 |
| Test qatorlari | 523 |
| Test / manba nisbati | 0.84 |
| Eng katta fayl, qator | 123 |
Test kodi manba kodidan ko'proq — bu normal va yaxshi belgi.
Eng katta fayl ham 150 qatordan oshmadi. Bu tasodif emas: har modul bitta ish qiladi.
Nimani boshqacha qilish mumkin edi
Halol bo'lish kerak — loyihada yechilmagan narsalar bor:
import pandas as pd show(pd.DataFrame([ {"cheklov": "oqi() butun faylni xotiraga o'qiydi", "qachon muammo": "1 GB dan katta fayl", "yechim": "generator (14-bob mashqi)"}, {"cheklov": "Faqat CSV formati", "qachon muammo": "Excel yoki Parquet kerak bo'lsa", "yechim": "o'qish qatlamini interfeysga ajratish"}, {"cheklov": "tarmoq.py ishlatilmayapti", "qachon muammo": "Ma'lumot API dan kelsa", "yechim": "oqish.py ga manba tanlash qo'shish"}, {"cheklov": "Sana faqat YYYY-MM-DD", "qachon muammo": "Boshqa formatdagi fayl", "yechim": "sozlamaga format qo'shish"}, {"cheklov": "Til qattiq yozilgan (o'zbekcha)", "qachon muammo": "Boshqa til kerak bo'lsa", "yechim": "gettext yoki xabarlar lug'ati"}, ]))
| cheklov | qachon muammo | yechim |
|---|---|---|
| oqi() butun faylni xotiraga o'qiydi | 1 GB dan katta fayl | generator (14-bob mashqi) |
| Faqat CSV formati | Excel yoki Parquet kerak bo'lsa | o'qish qatlamini interfeysga ajratish |
| tarmoq.py ishlatilmayapti | Ma'lumot API dan kelsa | oqish.py ga manba tanlash qo'shish |
| Sana faqat YYYY-MM-DD | Boshqa formatdagi fayl | sozlamaga format qo'shish |
| Til qattiq yozilgan (o'zbekcha) | Boshqa til kerak bo'lsa | gettext yoki xabarlar lug'ati |
Bularning hech biri hozir muammo emas. Ularni oldindan yechish 1-bobdagi qoidaga zid bo'lardi: "kelajakda kerak bo'lishi mumkin" — bu sabab emas.
Muhimi shundaki, ular yechilganda qayerga tegish kerakligi ma'lum. Tuzilish shu uchun kerak.
Keyingi qadam
import pandas as pd show(pd.DataFrame([ {"mavzu": "Ma'lumotlar bazasi", "nima o'rganish": "SQLAlchemy, migratsiyalar (alembic)"}, {"mavzu": "Veb API", "nima o'rganish": "FastAPI, pydantic, async"}, {"mavzu": "Konteyner", "nima o'rganish": "Docker, ko'p bosqichli qurish"}, {"mavzu": "Fon vazifalari", "nima o'rganish": "Celery yoki RQ, navbatlar"}, {"mavzu": "Kuzatuv", "nima o'rganish": "Tuzilgan jurnal, metrikalar, Sentry"}, {"mavzu": "MLOps", "nima o'rganish": "Model versiyalash, tajribalarni kuzatish (keyingi kitob)"}, ]))
| mavzu | nima o'rganish |
|---|---|
| Ma'lumotlar bazasi | SQLAlchemy, migratsiyalar (alembic) |
| Veb API | FastAPI, pydantic, async |
| Konteyner | Docker, ko'p bosqichli qurish |
| Fon vazifalari | Celery yoki RQ, navbatlar |
| Kuzatuv | Tuzilgan jurnal, metrikalar, Sentry |
| MLOps | Model versiyalash, tajribalarni kuzatish (keyingi kitob) |
Xulosa
| Fikr | Mazmuni |
|---|---|
| Ajratish | Har modul bitta ish qiladi; eng katta fayl 150 qatordan kam |
| Tekshiruv | Fayl chegarasida qat'iy, ichkarida ishonch |
| Xatolar | To'planadi yoki otiladi — ongli tanlov |
| Sozlama | Muhitdan, erta tekshiriladi |
| Testlar | Manba kodidan ko'proq — bu normal |
| Avtomatlashtirish | Bitta ./tekshir.sh hammasini tekshiradi |
| Halollik | Yechilmagan cheklovlarni biling va yozib qo'ying |
Talaba ishi
hisobot_matniuchun test yozing: bo'shNatijabilan yiqilmasligini tekshiring.--format markdownqo'shing vamatn.pygamarkdown_matniyozing.katta_sinov.csvni 500 000 qatorga kattalashtiring. Qaysi qadam eng sekin bo'ladi?tracemallocbilan xotirani o'lchang.- Loyihani o'zingizning ma'lumotingizga moslang: ustun nomlarini va qoidalarni o'zgartiring. Nechta faylga tegish kerak bo'ldi? Bu yaxshi ko'rsatkichmi?
Bu bobni bepul o'qidingiz.
Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.