Asosiy qismga o'tish

Shpargalka: tez ma'lumotnoma

18-bob 14 kod bloki 1829 so'z

Bu bob o'qish uchun emas, qarash uchun.

Yangi loyiha boshlash

bash7 qator
mkdir loyiha && cd loyiha
python3 -m venv .venv
.venv/bin/python3 -m pip install -U pip
mkdir -p src/paket tests
touch src/paket/__init__.py
# pyproject.toml yozing (pastda), keyin:
.venv/bin/python3 -m pip install -e ".[dev]"

pyproject.toml namunasi

python29 qator
[project]
name = "paket"
version = "0.1.0"
description = "Bir qatorlik tavsif"
readme = "README.md"
requires-python = ">=3.10"
license = {text = "MIT"}
dependencies = []

[project.optional-dependencies]
dev = ["pytest>=8", "pytest-cov>=5", "mypy>=1.8", "ruff>=0.5"]

[project.scripts]
paket = "paket.cli:main"

[build-system]
requires = ["setuptools>=68"]
build-backend = "setuptools.build_meta"

[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "-q --strict-markers"

[tool.coverage.run]
source = ["paket"]

[tool.coverage.report]
show_missing = true
exclude_lines = ["pragma: no cover", "if __name__ == .__main__.:"]

Loyiha tuzilishi

python18 qator
loyiha/
├── pyproject.toml
├── ruff.toml
├── mypy.ini
├── README.md
├── .gitignore
├── .env.namuna
├── src/paket/
│   ├── __init__.py       # ommaviy yuz: importlar + __version__
│   ├── __main__.py       # python3 -m paket
│   ├── cli.py            # argparse
│   ├── modellar.py       # dataclass, Enum
│   ├── sozlama.py        # muhit o'zgaruvchilari
│   ├── xatolar.py        # istisno oilasi
│   └── ...               # har modul bitta ish
└── tests/
    ├── conftest.py       # umumiy fixture lar (__init__.py YO'Q)
    └── test_*.py

Kundalik buyruqlar

python9 qator
.venv/bin/python3 -m pytest              # testlar
.venv/bin/python3 -m pytest --lf         # faqat oxirgi yiqilganlar
.venv/bin/python3 -m pytest -k "sana"    # nom bo'yicha
.venv/bin/python3 -m pytest --cov=paket --cov-report=term-missing
python3 -m mypy                          # turlar
ruff check src tests                     # linter
ruff check --fix src tests               # avtomatik tuzatish
ruff format src tests                    # formatlash
./tekshir.sh                             # hammasi

Turlar

python8 qator
def f(a: int, b: str = "x") -> bool: ...
xs: list[int] = []
d: dict[str, list[int]] = {}
t: tuple[int, str] = (1, "a")
ixtiyoriy: int | None = None              # 3.10+; eskisi Optional[int]
from collections.abc import Callable, Iterable, Sequence
fn: Callable[[int, str], bool]
from typing import Any, TypeVar, Protocol
Kirish turi Ishlating
Faqat aylanib chiqiladi Iterable[T]
Indeks va len kerak Sequence[T]
O'zgartiriladi list[T]
Qaytish turi Har doim aniq: list[T], dict[K, V]

dataclass

python13 qator
from dataclasses import dataclass, field, replace

@dataclass(frozen=True, slots=True)
class Model:
    ism: str
    baho: int = 0
    teglar: list[str] = field(default_factory=list)    # [] EMAS!

    @property
    def katta(self) -> bool:
        return self.baho > 90

yangi = replace(eski, baho=95)             # frozen da o'zgartirish

frozen=True — tasodifiy o'zgarishdan himoya. slots=True — imlo xatosini ushlaydi. Python 3.10 da ikkalasi birga tushunarsiz TypeError beradi (3.11 da tuzatilgan).

Istisnolar

python9 qator
class LoyihaXato(Exception): ...           # ildiz

class FaylXato(LoyihaXato):
    def __init__(self, yol: str, sabab: str) -> None:
        self.yol, self.sabab = yol, sabab  # MA'LUMOT saqlang, faqat matn emas
        super().__init__(f"{yol}: {sabab}")

raise Yangi(...) from e                    # sababni saqlash
raise Yangi(...) from None                 # sababni yashirish
Qilmang Qiling
except: except AniqXato:
except Exception: pass Jurnalga yozing yoki qayta oting
return -1 xato o'rniga raise
20 qatorli try Qisqa try, har tekshiruv alohida

Testlar

python28 qator
import pytest

@pytest.mark.parametrize("kirish, kutilgan", [("85", 85), ("0", 0)])
def test_holat(kirish, kutilgan):
    assert f(kirish) == kutilgan

def test_xato():
    with pytest.raises(ValueError, match="son emas"):
        f("abc")

@pytest.fixture
def malumot():
    return [1, 2, 3]

def test_fayl(tmp_path):                   # har testga yangi papka
    (tmp_path / "a.txt").write_text("x", encoding="utf-8")

def test_muhit(monkeypatch):               # vaqtincha o'zgartirish
    monkeypatch.setenv("KALIT", "qiymat")

def test_chiqish(capsys):                  # stdout/stderr ni ushlash
    print("salom")
    assert "salom" in capsys.readouterr().out

def test_jurnal(caplog):                   # jurnalni ushlash
    with caplog.at_level(logging.WARNING):
        ...
    assert "ogohlantirish" in caplog.text
Fixture Beradi
tmp_path Yangi bo'sh papka (Path)
capsys stdout / stderr matni
caplog Jurnal xabarlari
monkeypatch Vaqtincha setenv, setattr, chdir

Jurnal

python12 qator
import logging
log = logging.getLogger(__name__)          # HAR modulda

log.debug("tafsilot: %s", x)               # f-string emas, %s
log.info("ish tugadi: %d qator", n)
log.warning("%d qator rad etildi", k)
log.error("bajarilmadi: %s", e)
log.exception("kutilmagan xato")           # faqat except ichida, iz bilan

# FAQAT dastur sozlaydi, kutubxona emas:
logging.basicConfig(level=logging.INFO, stream=sys.stderr,
                    format="%(asctime)s %(levelname)-8s %(name)s: %(message)s")

Fayllar

python20 qator
from pathlib import Path

p = Path("malumot") / "2026" / "f.csv"
p.parent.mkdir(parents=True, exist_ok=True)
matn = p.read_text(encoding="utf-8")       # encoding HAR DOIM
p.write_text(matn, encoding="utf-8")
p.with_suffix(".json")
list(p.parent.glob("*.csv"))               # rglob — ichkilari bilan

import json
json.dumps(d, ensure_ascii=False, indent=2)     # o'zbekcha harflar uchun
json.dumps(d, default=str)                      # date, Decimal uchun

import csv
with p.open("w", encoding="utf-8", newline="") as f:    # newline="" MUHIM
    w = csv.DictWriter(f, fieldnames=[...])
    w.writeheader(); w.writerows(qatorlar)

import sqlite3
con.execute("SELECT * FROM t WHERE ism = ?", (ism,))    # ? — injection dan himoya

Konfiguratsiya

python12 qator
import os

def son(nom, sukut):
    xom = os.environ.get(nom)
    return sukut if not xom else int(xom)   # int() xato bersa — ushlang

def mantiqiy(nom, sukut):
    xom = os.environ.get(nom, "").lower()
    if not xom: return sukut
    if xom in {"1","true","ha","on"}: return True
    if xom in {"0","false","yo'q","off"}: return False
    raise ValueError(f"{nom}: mantiqiy qiymat kutilgan")

bool("false") → True. Hech qachon bool(os.environ.get(...)) yozmang.

Parallellik

python12 qator
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor, as_completed

with ThreadPoolExecutor(max_workers=8) as p:        # I/O uchun
    natijalar = list(p.map(f, elementlar))

with ProcessPoolExecutor(max_workers=4) as p:       # CPU uchun
    natijalar = list(p.map(f, elementlar))          # f import qilinadigan modulda bo'lsin!

with ThreadPoolExecutor() as p:
    kelajaklar = {p.submit(f, x): x for x in elementlar}
    for k in as_completed(kelajaklar):
        natija = k.result()
Ish Vosita
Fayl, tarmoq, baza (I/O) ThreadPoolExecutor
Hisob (CPU) ProcessPoolExecutor
Minglab ulanish asyncio
Kichik ish Oddiy sikl — parallellik qimmat

asyncio da time.sleep emas, await asyncio.sleep.

HTTP

python7 qator
import requests

j = requests.get(url, timeout=5)           # timeout MAJBURIY
j.raise_for_status()
malumot = j.json()

s = requests.Session()                     # ko'p so'rovda tezroq

Qayta urinish: faqat 408, 429, 5xx da. 404, 401 — darhol to'xtang. Kutish: eksponensial + jitter.

Tezlik

python12 qator
import time, timeit, cProfile, pstats, tracemalloc
from functools import lru_cache

t0 = time.perf_counter()                   # time.time() EMAS
timeit.timeit(lambda: f(), number=100)

cProfile.run("f()", sort="tottime")        # tottime — nishon, cumtime — yo'nalish

@lru_cache(maxsize=1024)
def qimmat(x): ...

tracemalloc.start(); f(); cho_qqi = tracemalloc.get_traced_memory()[1]
Muammo Yechim
x in ro'yxat sekin set yoki dict ishlating
Bir hisob takrorlanadi lru_cache
Katta fayl xotiraga sig'maydi Generator, qator-qator
Qayerda sekin — noma'lum cProfile, taxmin qilmang

Eng ko'p uchraydigan xatolar

Xato Oqibati To'g'risi
def f(x=[]) Ro'yxat chaqiruvlar orasida saqlanadi x=None, ichida []
== None __eq__ yolg'on gapirishi mumkin is None
except: Ctrl+C ham yutiladi except AniqXato:
open(yol) Platformaga bog'liq kodlash encoding="utf-8"
requests.get(url) Cheksiz osilish timeout=5
bool("false") True Qo'lda tahlil qiling
f-string jurnалда Har doim hisoblanadi log.debug("%s", x)
csv + newline=None Windows da bo'sh qatorlar newline=""
json.py fayl nomi Standart kutubxonani berkitadi Boshqa nom
tests/__init__.py pytest import muammosi Yaratmang
SQL da f-string SQL injection ? parametri
time.sleep async da Butun tsikl bloklanadi await asyncio.sleep
Global SOZLAMA Testlar bir-biriga ta'sir qiladi Argument sifatida uzating
sys.exit() main() ichida Testdan chaqirib bo'lmaydi return kod

Qaytish kodlari

Kod Ma'nosi
0 Muvaffaqiyat
1 Umumiy xato
2 Noto'g'ri ishlatish (argument, sozlama)
130 Ctrl+C

Tekshiruv ro'yxati: yakunlashdan oldin

  • [ ] ./tekshir.sh toza o'tadi (format, linter, turlar, testlar)
  • [ ] Qamrov maqbul (60%+); Missing qatorlari ko'rib chiqilgan
  • [ ] README.md da o'rnatish va uchta ishlatish misoli bor
  • [ ] .env .gitignore da; .env.namuna yozilgan
  • [ ] Kodda parol, token, kalit yo'q (git log -p | grep -i "key\|token\|parol")
  • [ ] Xato xabarlari foydalanuvchi uchun tushunarli, stderr ga chiqadi
  • [ ] Qaytish kodlari to'g'ri
  • [ ] main(argv) testdan chaqirilishi mumkin
  • [ ] Har tashqi so'rovda timeout bor
  • [ ] Har open() da encoding bor
  • [ ] Eng katta fayl 400 qatordan kam
  • [ ] Yechilmagan cheklovlar README yoki izohda yozilgan

Kitobdagi o'lchovlar

Bob O'lchangan natija
1 Skript 9 qator, ajratilgan variant 50 — lekin u qaysi qator nega rad etilganini aytadi
2 Bitta requests bilan birga 4 ta bog'liqlik keldi
4 slots=True imlo xatosini ushladi; slots siz u jim o'tdi
5 --strict siz mypy turlanmagan kodni umuman tekshirmaydi
7 100% qamrov hech narsani tekshirmaydigan test bilan ham olinadi
9 isEnabledFor bilan o'chiq DEBUG deyarli 0 ms
10 latin-1 xato bermaydi, lekin matnni buzadi
13 CPU ishida thread lar foyda bermadi, jarayonlar berdi
14 Generator ro'yxatdan yuzlab barobar kam xotira oldi
16 B006 va E711 — linter topgan haqiqiy xatolar

Kitobning asosiy g'oyasi: har bir tanlovni o'lchang va tekshiring. "Ishlayotganga o'xshaydi" — bu dalil emas.

Bu bobni bepul o'qidingiz.

Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.

Telegramda yozish Narxlar