IlmHamroh
Python kursi/Sifat va vositalar2/8-dars18 daqiqa
Mundarija (22)

18.2-dars: pip va bog'liqliklar

18-QISM — SIFAT VA VOSITALAR · 2-dars


1. Kirish va motivatsiya

O'tgan darsda virtual muhit yaratdik. Endi unga kutubxonalarni o'rnatishni va — eng muhimi — bog'liqliklarni to'g'ri boshqarishni o'rganamiz. pip — Python'ning paket menejeri: u kutubxonalarni PyPI (Python Package Index) dan yuklab, muhitingizga o'rnatadi. Ammo pip install requests yozish oson bo'lsa-da, versiyalarni to'g'ri belgilash, bog'liqliklarni hujjatlash va to'qnashuvlarni hal qilish alohida mahorat talab qiladi.

Bog'liqliklarni noto'g'ri boshqarish real muammolarga olib keladi: bugun ishlagan kod ertaga kutubxona yangilanganda buziladi, yoki loyiha boshqa kompyuterda aynan takrorlanmaydi.

Real vaziyat. Bir jamoa requirements.txt da faqat kutubxona nomlarini yozgan edi: requests, flask, pandas — versiyasiz. Loyiha olti oy ishladi. Keyin yangi dasturchi qo'shildi, pip install -r requirements.txt qildi — va loyiha buzildi. Sabab: shu olti oyda pandas yangi asosiy versiyaga o'tgan va API o'zgargan edi. Versiya belgilanmagani uchun yangi dasturchi eski koddan farqli, mos kelmaydigan versiyani oldi. Ular versiyalarni aniq belgilashdi (pandas>=2.0,<3.0) va aniq versiyalarni pip freeze bilan qulfladilar. Endi loyiha har joyda aynan bir xil ishlaydi.

Bu darsda pip bilan bog'liqliklarni professional boshqarishni o'rganamiz.

Bu darsda:

  • pip install, uninstall, list, show
  • Versiya belgilagichlari (==, >=, ~=, <)
  • requirements.txt — bog'liqliklar ro'yxati
  • pip freeze — aniq versiyalarni qulflash
  • Bog'liqlik daraxti va to'qnashuvlar
  • Qulflash (lock) va takrorlanuvchanlik
  • Xavfsizlik: ishonchli manba, pip-audit
  • Amaliy: bog'liqlik boshqaruvi ish oqimi

ℹ Misollarda versiya mantig'i uchun packaging moduli, haqiqiy o'rnatish uchun pip (subprocess) ishlatiladi.


2. Nazariya — chuqur tushuntirish

2.1. Asosiy pip buyruqlari

bash
pip install requests               # eng so'nggi mos versiya
pip install requests==2.31.0       # aniq versiya
pip install -r requirements.txt    # fayldan hammasi
pip uninstall requests             # o'chirish
pip list                           # o'rnatilgan paketlar
pip show requests                  # paket haqida (versiya, bog'liqliklar)
pip install --upgrade requests     # yangilash
Buyruq Nima qiladi
install Paketni PyPI dan o'rnatadi
uninstall O'chiradi
list O'rnatilganlar ro'yxati
show Paket metama'lumoti va bog'liqliklari
freeze Aniq versiyalar (requirements.txt uchun)
--upgrade Yangi versiyaga

2.2. Versiya belgilagichlari

Semantik versiyalash (SemVer): ASOSIY.KICHIK.PATCH (masalan 2.31.4):

Belgilagich Ma'nosi Misol
==2.31.0 Aniq shu versiya Faqat 2.31.0
>=2.31 Shu yoki yangiroq 2.31, 2.35, 3.0
>=2.31,<3.0 Oralik 2.31–2.x, 3.0 emas
~=2.31 Mos (patch/kichik o'sadi) 2.31–2.x, 3.0 emas
!=2.30 Bundan tashqari 2.30 emas
>2.31 Qat'iy katta 2.31 emas

~=2.31 (compatible release) — "shu kichik versiya ichida yangilanishlar, lekin keyingi asosiy versiya emas". ~=2.31 ≡ >=2.31,<3.0.

2.3. Semantik versiyalash ma'nosi

O'zgarish Ma'nosi Misol
ASOSIY (major) Moslikni buzuvchi 2.x → 3.0
KICHIK (minor) Yangi imkoniyat, mos 2.31 → 2.32
PATCH Xato tuzatish 2.31.0 → 2.31.1

Qoida: yangi asosiy versiya (3.0) API ni buzishi mumkin — shuning uchun <3.0 bilan cheklash xavfsiz.

2.4. requirements.txt

Loyihaning bog'liqliklari matn fayl sifatida:

requests>=2.31,<3.0
flask~=3.0
pandas>=2.0
python-dotenv==1.0.0      # aniq
bash
pip install -r requirements.txt    # hammasini o'rnatadi

requirements.txt git'ga qo'shiladi 18.1-bob — loyihani boshqa kompyuterda takrorlash uchun retsept.

2.5. pip freeze — qulflash

pip freeze o'rnatilgan aniq versiyalarni beradi:

bash
pip freeze > requirements.txt
requests==2.31.0
urllib3==2.1.0            # requests ning bog'liqligi ham
certifi==2023.11.17

Farq: requirements.txt ni qo'lda yozganda oraliqlar (>=2.31), freeze da aniq versiyalar (==2.31.0). Ikki yondashuv:

Yondashuv Foyda
Oraliq (>=2.31,<3.0) Xavfsizlik yangilanishlarini oladi
Aniq (freeze) To'liq takrorlanuvchanlik

2.6. Bog'liqlik daraxti va to'qnashuvlar

Har paket o'z bog'liqliklariga ega — bog'liqlik daraxti:

mening_loyiha
├── requests>=2.31
│   ├── urllib3>=1.21
│   └── certifi
└── flask~=3.0
    └── werkzeug>=3.0

To'qnashuv: A paket urllib3<2, B paket urllib3>=2 talab qilsa, pip ikkalasini qanoatlantira olmaydi:

ERROR: Cannot install ... because these package versions have conflicting dependencies

pip bog'liqliklarni hal qiluvchi (resolver) ga ega — u mos versiyalar to'plamini topishga harakat qiladi; topa olmasa xato beradi.

2.7. Qulflash (lock) va takrorlanuvchanlik

To'liq takrorlanuvchanlik uchun barcha (bilvosita ham) versiyalarni qulflash kerak:

Vosita Qulflash usuli
pip freeze Barcha aniq versiyalar
pip-tools (pip-compile) requirements.in → qulflangan requirements.txt
poetry (18.3) poetry.lock
uv (18.3) uv.lock

Qulf fayli (lock) — aynan qaysi versiyalar o'rnatilganini yozadi, shu jumladan xesh (yaxlitlik uchun).

2.8. Xavfsizlik

Xavf Himoya
Zararli paket (typosquatting) Nomni diqqat bilan tekshiring (reqeusts emas requests)
Zaif versiyalar pip-audit — ma'lum zaifliklarni tekshiradi
Ishonchsiz manba Faqat PyPI yoki ishonchli indeks
Qulflanmagan bog'liqlik Kutilmagan yangilanish
bash
pip install pip-audit
pip-audit                          # ma'lum zaifliklarni tekshiradi

pip install PyPI dan istalgan kodni o'rnatadi va uni ishga tushiradi (setup skriptlari) — nom to'g'riligini va manbani tekshiring.


3. Tez ma'lumotnoma

bash
pip install "requests>=2.31,<3.0"       # oralik
pip install requests==2.31.0            # aniq
pip install -r requirements.txt         # fayldan
pip install --upgrade requests          # yangilash
pip freeze > requirements.txt           # qulflash
pip show requests                       # metama'lumot
pip list --outdated                     # eskirgan paketlar
pip-audit                               # xavfsizlik
# requirements.txt
requests>=2.31,<3.0
flask~=3.0
python-dotenv==1.0.0

Qoidalar

versiyani belgilang (nomsiz emas): >=2.31,<3.0
~=2.31 — kichik versiyalar, asosiy emas
requirements.txt git'ga; muhit git'ga emas
takrorlanuvchanlik — pip freeze yoki lock fayl
xavfsizlik: nomni tekshiring, pip-audit
yangi asosiy versiya (3.0) — API ni buzishi mumkin

4. Batafsil misollar

Misollarda versiya mantig'i uchun packaging, haqiqiy pip uchun subprocess ishlatiladi.

Misol 1 — Versiya belgilagichlari

python
"""SemVer taqqoslash; belgilagichlar ==, >=, ~=, oralik; qaysi versiyalar mos keladi; ~= mantig'i (asosiy versiya cheklanadi)."""

from packaging.specifiers import SpecifierSet
from packaging.version import Version


def main() -> None:
    print("=== 1. Versiya taqqoslash (SemVer) ===")
    print(f"  2.31.0 > 2.20.0: {Version('2.31.0') > Version('2.20.0')}")
    print(f"  2.31.0 > 2.31: {Version('2.31.0') > Version('2.31')}")
    print(f"  3.0 > 2.99: {Version('3.0') > Version('2.99')}")

    print("\n=== 2. Belgilagichlar — qaysi versiyalar mos ===")
    versiyalar = ["2.20.0", "2.31.0", "2.35.0", "3.0.0", "3.1.0"]
    belgilagichlar = ["==2.31.0", ">=2.31", ">=2.31,<3.0", "~=2.31", "!=2.31.0"]
    for belgi in belgilagichlar:
        spec = SpecifierSet(belgi)
        mos = [v for v in versiyalar if Version(v) in spec]
        print(f"  {belgi:15} → {mos}")

    print("\n=== 3. ~= (compatible release) mantig'i ===")
    print(f"  ~=2.31 ≡ >=2.31,<3.0")
    print(f"  2.35 mos: {Version('2.35') in SpecifierSet('~=2.31')}")
    print(f"  3.0 mos: {Version('3.0') in SpecifierSet('~=2.31')}  ← asosiy versiya o'tmaydi")
    print(f"  ~=2.31.1 (patch): 2.31.5 mos {Version('2.31.5') in SpecifierSet('~=2.31.1')}, "
          f"2.32 mos {Version('2.32') in SpecifierSet('~=2.31.1')}")

    print("\n=== 4. SemVer o'zgarish turlari ===")
    ozgarishlar = [
        ("2.31.0", "2.31.1", "PATCH — xato tuzatish, xavfsiz"),
        ("2.31.0", "2.32.0", "KICHIK — yangi imkoniyat, mos"),
        ("2.31.0", "3.0.0", "ASOSIY — moslikni buzishi mumkin"),
    ]
    for eski, yangi, izoh in ozgarishlar:
        print(f"  {eski} → {yangi}: {izoh}")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Versiya taqqoslash (SemVer) ===
  2.31.0 > 2.20.0: True
  2.31.0 > 2.31: False
  3.0 > 2.99: True

=== 2. Belgilagichlar — qaysi versiyalar mos ===
  ==2.31.0        → ['2.31.0']
  >=2.31          → ['2.31.0', '2.35.0', '3.0.0', '3.1.0']
  >=2.31,<3.0     → ['2.31.0', '2.35.0']
  ~=2.31          → ['2.31.0', '2.35.0']
  !=2.31.0        → ['2.20.0', '2.35.0', '3.0.0', '3.1.0']

=== 3. ~= (compatible release) mantig'i ===
  ~=2.31 ≡ >=2.31,<3.0
  2.35 mos: True
  3.0 mos: False  ← asosiy versiya o'tmaydi
  ~=2.31.1 (patch): 2.31.5 mos True, 2.32 mos False

=== 4. SemVer o'zgarish turlari ===
  2.31.0 → 2.31.1: PATCH — xato tuzatish, xavfsiz
  2.31.0 → 2.32.0: KICHIK — yangi imkoniyat, mos
  2.31.0 → 3.0.0: ASOSIY — moslikni buzishi mumkin

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

Misol 2 — requirements.txt va bog'liqlik tahlili

python
"""requirements.txt ni tahlil qilish; Requirement bilan nom, extras, belgilagich ajratish; oraliq vs aniq versiya; bog'liqlik tekshiruvi."""

from packaging.requirements import Requirement
from packaging.specifiers import SpecifierSet
from packaging.version import Version

REQUIREMENTS = """# Loyiha bog'liqliklari
requests>=2.31,<3.0
flask~=3.0
pandas>=2.0
python-dotenv==1.0.0
requests[security]>=2.31          # extras bilan
"""


def main() -> None:
    print("=== 1. requirements.txt ni tahlil qilish ===")
    for qator in REQUIREMENTS.splitlines():
        qator = qator.split("#")[0].strip()
        if not qator:
            continue
        r = Requirement(qator)
        extras = f" extras={r.extras}" if r.extras else ""
        print(f"  {r.name:16} belgilagich: {str(r.specifier) or '(yo`q)':20}{extras}")

    print("\n=== 2. Belgilagich turi ===")
    talablar = ["requests>=2.31,<3.0", "flask~=3.0", "python-dotenv==1.0.0", "pandas"]
    for t in talablar:
        r = Requirement(t)
        if not str(r.specifier):
            tur = "⚠️ versiyasiz (xavfli)"
        elif "==" in str(r.specifier):
            tur = "aniq (qulflangan)"
        else:
            tur = "oraliq (moslashuvchan)"
        print(f"  {r.name:16} {tur}")

    print("\n=== 3. O'rnatilgan versiya mosligini tekshirish ===")
    ornatilgan = {"requests": "2.31.4", "flask": "3.0.1", "pandas": "2.1.0", "python-dotenv": "1.0.0"}
    for qator in REQUIREMENTS.splitlines():
        qator = qator.split("#")[0].strip()
        if not qator:
            continue
        r = Requirement(qator)
        if r.name in ornatilgan:
            versiya = ornatilgan[r.name]
            mos = Version(versiya) in r.specifier if str(r.specifier) else True
            print(f"  {r.name:16} {versiya} {'✅ mos' if mos else '❌ mos emas'} ({r.specifier})")

    print("\n=== 4. Oraliq vs aniq ===")
    print("  oraliq (>=2.31,<3.0): xavfsizlik yangilanishlarini oladi, moslashuvchan")
    print("  aniq (==2.31.4, freeze): to'liq takrorlanuvchanlik")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. requirements.txt ni tahlil qilish ===
  requests         belgilagich: <3.0,>=2.31
  flask            belgilagich: ~=3.0
  pandas           belgilagich: >=2.0
  python-dotenv    belgilagich: ==1.0.0
  requests         belgilagich: >=2.31               extras={'security'}

=== 2. Belgilagich turi ===
  requests         oraliq (moslashuvchan)
  flask            oraliq (moslashuvchan)
  python-dotenv    aniq (qulflangan)
  pandas           ⚠️ versiyasiz (xavfli)

=== 3. O'rnatilgan versiya mosligini tekshirish ===
  requests         2.31.4 ✅ mos (<3.0,>=2.31)
  flask            3.0.1 ✅ mos (~=3.0)
  pandas           2.1.0 ✅ mos (>=2.0)
  python-dotenv    1.0.0 ✅ mos (==1.0.0)
  requests         2.31.4 ✅ mos (>=2.31)

=== 4. Oraliq vs aniq ===
  oraliq (>=2.31,<3.0): xavfsizlik yangilanishlarini oladi, moslashuvchan
  aniq (==2.31.4, freeze): to'liq takrorlanuvchanlik

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

Misol 3 — Haqiqiy pip buyruqlari

python
"""virtual muhitda haqiqiy pip: install, list, show; bog'liqliklar; pip freeze; chiqish normallashtiriladi."""

import subprocess
import sys
import tempfile
from pathlib import Path


def main() -> None:
    with tempfile.TemporaryDirectory() as katalog:
        r = Path(katalog)
        muhit = r / ".venv"
        subprocess.run([sys.executable, "-m", "venv", str(muhit)], capture_output=True, text=True)
        bin_papka = "Scripts" if sys.platform == "win32" else "bin"
        py = muhit / bin_papka / ("python.exe" if sys.platform == "win32" else "python")

        print("=== 1. Toza muhitdagi paketlar ===")
        natija = subprocess.run([str(py), "-m", "pip", "list", "--format=freeze"],
                                capture_output=True, text=True)
        paketlar = sorted(q.split("==")[0] for q in natija.stdout.splitlines() if "==" in q)
        print(f"  boshlang'ich paketlar: {paketlar}")

        print("\n=== 2. pip show (mahalliy paket) ===")
        # pip'ning o'zini ko'ramiz (tarmoqsiz)
        natija = subprocess.run([str(py), "-m", "pip", "show", "pip"],
                                capture_output=True, text=True)
        for qator in natija.stdout.splitlines():
            if qator.startswith(("Name:", "Summary:", "Requires:")):
                print(f"  {qator}")

        print("\n=== 3. requirements.txt yozish ===")
        req = r / "requirements.txt"
        req.write_text("# namuna\nrequests>=2.31,<3.0\nflask~=3.0\n", encoding="utf-8")
        print(f"  requirements.txt yaratildi: {req.exists()}")
        for qator in req.read_text(encoding="utf-8").splitlines():
            print(f"    {qator}")

        print("\n=== 4. pip freeze (aniq versiyalar) ===")
        natija = subprocess.run([str(py), "-m", "pip", "freeze"], capture_output=True, text=True)
        freeze_qatorlar = natija.stdout.splitlines()
        print(f"  freeze qatorlari soni: {len(freeze_qatorlar)}")
        print(f"  har qator '==' bilan aniq versiya: {all('==' in q or q.startswith('-') for q in freeze_qatorlar) if freeze_qatorlar else True}")
        print("  ⭐ freeze — aynan o'rnatilgan versiyalar (takrorlanuvchanlik uchun)")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Toza muhitdagi paketlar ===
  boshlang'ich paketlar: ['pip']

=== 2. pip show (mahalliy paket) ===
  Name: pip
  Summary: The PyPA recommended tool for installing Python packages.
  Requires:

=== 3. requirements.txt yozish ===
  requirements.txt yaratildi: True
    # namuna
    requests>=2.31,<3.0
    flask~=3.0

=== 4. pip freeze (aniq versiyalar) ===
  freeze qatorlari soni: 0
  har qator '==' bilan aniq versiya: True
  ⭐ freeze — aynan o'rnatilgan versiyalar (takrorlanuvchanlik uchun)

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

Misol 4 — Amaliy: bog'liqlik boshqaruvi ish oqimi

Loyiha bog'liqliklarini to'g'ri boshqaruvchi yordamchi yozamiz: requirements.txt ni tahlil qiladi, versiyasiz (xavfli) yozuvlarni topadi, o'rnatilgan versiyalar mosligini tekshiradi, va oddiy "audit" (ma'lum zaif versiyalarni ro'yxatga solishtirish) qiladi. Bu — real loyihada bog'liqliklarni sog'lom tutishning namunasi.

python
"""bog'liqlik boshqaruvi: requirements tahlili, versiyasiz yozuvlarni topish, o'rnatilgan mosligini tekshirish, oddiy xavfsizlik auditi (zaif versiyalar ro'yxati)."""

from packaging.requirements import Requirement
from packaging.version import Version

REQUIREMENTS = """requests>=2.31,<3.0
flask~=3.0
pandas
urllib3>=1.26
pyyaml==5.3.1
"""

# O'rnatilgan (pip freeze natijasini soddalashtirilgan)
ORNATILGAN = {
    "requests": "2.31.4",
    "flask": "3.0.1",
    "pandas": "2.1.0",
    "urllib3": "1.26.5",
    "pyyaml": "5.3.1",
}

# Ma'lum zaif versiyalar (soddalashtirilgan namuna — haqiqatda pip-audit qiladi)
ZAIF = {
    "pyyaml": ("<5.4", "CVE-2020-14343: yaml.load bilan RCE"),
    "urllib3": ("<1.26.5", "CVE-2021-33503: ReDoS"),
}


def tekshir(requirements: str) -> dict:
    hisobot = {"versiyasiz": [], "mos_emas": [], "zaif": [], "yaxshi": []}
    for qator in requirements.splitlines():
        qator = qator.split("#")[0].strip()
        if not qator:
            continue
        r = Requirement(qator)
        if not str(r.specifier):
            hisobot["versiyasiz"].append(r.name)
        versiya = ORNATILGAN.get(r.name)
        if versiya and str(r.specifier) and Version(versiya) not in r.specifier:
            hisobot["mos_emas"].append(f"{r.name} {versiya} ∉ {r.specifier}")
        if r.name in ZAIF and versiya:
            shart, tavsif = ZAIF[r.name]
            from packaging.specifiers import SpecifierSet
            if Version(versiya) in SpecifierSet(shart):
                hisobot["zaif"].append(f"{r.name} {versiya}: {tavsif}")
            else:
                hisobot["yaxshi"].append(r.name)
    return hisobot


def main() -> None:
    hisobot = tekshir(REQUIREMENTS)

    print("=== 1. ⚠️ Versiyasiz bog'liqliklar (xavfli) ===")
    for nom in hisobot["versiyasiz"]:
        print(f"  ❌ {nom} — versiya belgilanmagan, kutilmagan yangilanish xavfi")
        print(f"     tavsiya: {nom}>=<joriy>,<keyingi-asosiy>")

    print("\n=== 2. Mos kelmaydigan versiyalar ===")
    if hisobot["mos_emas"]:
        for m in hisobot["mos_emas"]:
            print(f"  ❌ {m}")
    else:
        print("  ✅ barcha o'rnatilgan versiyalar belgilagichga mos")

    print("\n=== 3. ⚠️ Xavfsizlik auditi ===")
    for z in hisobot["zaif"]:
        print(f"  🔴 {z}")
    print("  ⭐ haqiqiy loyihada: pip-audit bu tekshiruvni avtomatik qiladi")

    print("\n=== 4. Tavsiyalar ===")
    print("  1. Har bog'liqlikka versiya oralig'i belgilang (>=X,<keyingi-asosiy)")
    print("  2. pip freeze bilan aniq versiyalarni qulflang (takrorlanuvchanlik)")
    print("  3. pip-audit bilan muntazam xavfsizlik tekshiruvi")
    print("  4. Yangilanishlarni sinab, keyin qabul qiling")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. ⚠️ Versiyasiz bog'liqliklar (xavfli) ===
  ❌ pandas — versiya belgilanmagan, kutilmagan yangilanish xavfi
     tavsiya: pandas>=<joriy>,<keyingi-asosiy>

=== 2. Mos kelmaydigan versiyalar ===
  ✅ barcha o'rnatilgan versiyalar belgilagichga mos

=== 3. ⚠️ Xavfsizlik auditi ===
  🔴 pyyaml 5.3.1: CVE-2020-14343: yaml.load bilan RCE
  ⭐ haqiqiy loyihada: pip-audit bu tekshiruvni avtomatik qiladi

=== 4. Tavsiyalar ===
  1. Har bog'liqlikka versiya oralig'i belgilang (>=X,<keyingi-asosiy)
  2. pip freeze bilan aniq versiyalarni qulflang (takrorlanuvchanlik)
  3. pip-audit bilan muntazam xavfsizlik tekshiruvi
  4. Yangilanishlarni sinab, keyin qabul qiling

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


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

Noto'g'ri fikr To'g'risi
"requirements.txt da faqat nom yozsam bo'ladi" Versiya belgilang — kutilmagan yangilanish xavfi
">=2.31 xavfsiz" 3.0 API ni buzishi mumkin — <3.0 qo'shing
"pip install doim eng yaxshi versiyani beradi" Eng so'nggi mos — belgilagichga bog'liq
"freeze va qo'lda requirements bir xil" freeze aniq, qo'lda oraliq
"Bog'liqlik faqat men yozganlar" Bilvosita (transitiv) bog'liqliklar ham
"To'qnashuv bo'lmaydi" A urllib3<2, B >=2 — to'qnashadi
"pip install xavfsiz" Istalgan kodni ishga tushiradi — nomni tekshiring
"Yangilanish har doim yaxshi" Sinab, keyin qabul qiling

6. Keng tarqalgan xatolar va yechimlari

1. Versiyasiz bog'liqlik

requests                            # ❌ kutilmagan yangilanish
requests>=2.31,<3.0                 # ✅ oraliq

2. Faqat >= (yuqori chegara yo'q)

pandas>=2.0                         # ⚠️ 3.0 API ni buzishi mumkin
pandas>=2.0,<3.0                    # ✅

3. Bog'liqliklarni hujjatlamaslik

bash
pip install requests               # ❌ requirements.txt yangilanmaydi
pip install requests && pip freeze > requirements.txt   # ✅

4. Muhitni faollashtirmasdan o'rnatish

bash
pip install requests               # ❌ tizimga
source .venv/bin/activate && pip install requests   # ✅

5. To'qnashuvni e'tiborsiz qoldirish

bash
pip install "a" "b"                 # ❌ ERROR: conflicting dependencies
# ✅ mos versiyalarni toping yoki bittasini o'zgartiring

6. Typosquatting (nom xatosi)

bash
pip install reqeusts               # ❌ zararli paket bo'lishi mumkin
pip install requests               # ✅ nomni tekshiring

7. Xavfsizlik tekshiruvisiz

bash
# eski, zaif versiyalar bilan ishlash   # ❌
pip-audit                          # ✅ muntazam tekshiring

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 18.1-dars (o'tilgan): venv — pip muhitga o'rnatadi
  • 18.3-dars: poetry, uv — bog'liqlik va qulflashni birga
  • 19-qism: paketlash — o'z paketingizni PyPI ga nashr
  • 28-qism: CI/CD — bog'liqliklarni o'rnatish va audit
  • 29-qism: miqyoslash — bog'liqliklar hajmi va yuklanish

8. Eng yaxshi amaliyotlar

  1. Har bog'liqlikka versiya oralig'i belgilang (>=X,<keyingi-asosiy).

  2. ~= bilan kichik yangilanishlarga ruxsat, asosiyni cheklang.

  3. requirements.txt ni git'ga qo'shing va yangilab boring.

  4. Takrorlanuvchanlik uchun pip freeze yoki lock fayl.

  5. Muntazam pip-audit bilan zaifliklarni tekshiring.

  6. Paket nomini diqqat bilan tekshiring (typosquatting).

  7. Yangilanishlarni testlar bilan sinab, keyin qabul qiling.

  8. Bilvosita bog'liqliklarni ham hisobga oling (bog'liqlik daraxti).


9. Amaliy topshiriq

Vazifa 1: Natijani bashorat qiling

python
from packaging.version import Version
from packaging.specifiers import SpecifierSet
1.  print(Version("2.31.0") > Version("2.9.0"))
2.  print(Version("2.31.0") in SpecifierSet("==2.31.0"))
3.  print(Version("2.35") in SpecifierSet(">=2.31,<3.0"))
4.  print(Version("3.0") in SpecifierSet(">=2.31,<3.0"))
5.  print(Version("2.35") in SpecifierSet("~=2.31"))
6.  print(Version("3.0") in SpecifierSet("~=2.31"))
7.  print(Version("2.31.1") in SpecifierSet("~=2.31.0"))
8.  print(Version("2.32") in SpecifierSet("~=2.31.0"))
9.  print(Version("2.31.0") in SpecifierSet("!=2.31.0"))
10. print(Version("1.0.0") > Version("1.0"))
11. print(Version("2.0.0rc1") < Version("2.0.0"))
12. print(len([v for v in ["1.0", "2.0", "3.0"] if Version(v) in SpecifierSet(">=2.0")]))
Javoblar
  1. True
  2. True
  3. True
  4. False
  5. True
  6. False — ~=2.31 asosiy versiyani cheklaydi
  7. True
  8. False — ~=2.31.0 faqat patch (2.31.x)
  9. False — istisno qilingan
  10. False — teng (1.0.0 == 1.0)
  11. True — rc (release candidate) < barqaror
  12. 2 (2.0 va 3.0)

Vazifa 2: Xatolarni tuzating

1.  # requirements.txt:
    requests
    flask
    pandas

2.  # requirements.txt:
    pandas>=2.0

3.  # loyihani ko'chirdik:
    # faqat kod, requirements.txt yo'q

4.  # o'rnatish:
    pip install reqeusts

5.  # eski loyiha:
    pyyaml==5.3.1        # ma'lum zaiflik bor
Javoblar
1.  # requirements.txt (versiya belgilangan):
    requests>=2.31,<3.0
    flask~=3.0
    pandas>=2.0,<3.0

2.  # yuqori chegara qo'shildi:
    pandas>=2.0,<3.0

3.  # avval:
    pip freeze > requirements.txt   # git'ga qo'shing
    # ko'chirgach:
    pip install -r requirements.txt

4.  pip install requests            # nomni tekshiring

5.  pyyaml>=6.0                      # zaiflik tuzatilgan versiya
    # va: pip-audit bilan tekshiring

Vazifa 3: requirements tekshiruvchi

requirements.txt ni tekshiruvchi CLI:

  1. Har yozuvni tahlil qiling (packaging.Requirement)
  2. Versiyasiz yozuvlarni ogohlantiring
  3. Yuqori chegarasiz (>= faqat) yozuvlarni belgilang
  4. Chiqish kodi bilan (toza — 0, muammo — 1)

Vazifa 4: Bog'liqlik daraxti

pip show chiqishidan foydalanib:

  1. Paketning bevosita bog'liqliklarini oling (Requires:)
  2. Rekursiv to'liq daraxtni quring
  3. Umumiy (bir necha paket ishlatadigan) bog'liqliklarni toping
  4. Daraxtni chiroyli chiqaring (ichma-ich)

Vazifa 5: Versiya oralig'i taklif qiluvchi

  1. O'rnatilgan versiyani oling (pip show)
  2. Xavfsiz oraliq taklif qiling (~= yoki >=joriy,<keyingi-asosiy)
  3. requirements.txt ni yangilang
  4. pip freeze bilan solishtiring

Vazifa 6: Oddiy audit

  1. requirements.txt ni o'qing
  2. Ma'lum zaif versiyalar ro'yxati (JSON) bilan solishtiring
  3. Zaif paketlar uchun tavsiya bering
  4. pip-audit chiqishi bilan solishtiring (ixtiyoriy)

Vazifa 7: O'ylash

2022-yilda PyTorch loyihasi bog'liqlik chalkashligi (dependency confusion) hujumiga uchradi: kimdir PyPI ga loyihaning ichki paketiga o'xshash nomli zararli paket yukladi va u avtomatik o'rnatildi. Bu — bog'liqlik boshqaruvining xavfsizlik jihati. Nima uchun paket menejerlari bunday hujumlarga zaif, va bog'liqliklarni ishonchli boshqarish qanday tamoyillarga asoslanishi kerak?

Javob

Qisqa javob: Paket menejerlari zaif, chunki ular ishonch modeliga tayanadi: pip install X PyPI dan X nomli paketni oladi va uning kodini (setup skriptlarini) ishga tushiradi — bu kod nima qilishini oldindan tekshirmaydi. Hujumkorlar buni nomlar chalkashligi (typosquatting, dependency confusion) yoki buzilgan paket orqali ishlatadi. Ishonchli boshqaruv qulflash (aniq versiya + xesh), audit (zaifliklarni tekshirish) va manba nazorati (faqat ishonchli indeks) tamoyillariga asoslanadi.

1. Nega zaif

Zaiflik Tafsilot
Kod ishga tushadi setup.py/build skriptlari
Nom asosidagi ishonch X — qaysi X?
Ochiq nashr Har kim paket yuklashi mumkin
Avtomatik o'rnatish Bilvosita bog'liqliklar
Ichki vs ommaviy Dependency confusion

2. Hujum turlari

Hujum Qanday
Typosquatting reqeusts (requests o'rniga)
Dependency confusion Ichki nomga o'xshash ommaviy paket
Buzilgan paket Mavjud paketga zararli kod qo'shish
Zaif bog'liqlik Ma'lum CVE bilan versiya

3. Ishonchli boshqaruv tamoyillari

Tamoyil Amalda
Qulflash Aniq versiya + xesh (--require-hashes)
Audit pip-audit, muntazam tekshiruv
Manba nazorati Faqat rasmiy PyPI yoki ichki indeks
Minimal bog'liqlik Kamroq paket — kamroq xavf
Nomni tekshirish Har o'rnatishda diqqat
Ichki paketlarni himoya Nom bandligi, alohida indeks

4. Zamonaviy himoya

Vosita Nima beradi
Xesh tekshiruvi Paket o'zgarmaganini kafolatlaydi
pip-audit, safety Zaifliklarni topadi
SBOM (Software Bill of Materials) Bog'liqliklar ro'yxati
Sigstore Paketlarni imzolash
Lock fayllar Aynan nima o'rnatilganini yozadi

5. Muhandislik saboqlari

  1. pip install — kod ishga tushirish, faqat ma'lumot olish emas
  2. Ishonch — nomga emas, xesh va manbaga
  3. Qulflash + audit — asosiy himoya
  4. Kamroq bog'liqlik — kamroq hujum yuzasi

6. Xulosa

  1. Paket menejerlari ishonch modeliga tayanadi va kod ishga tushiradi
  2. Typosquatting va dependency confusion — asosiy hujumlar
  3. Qulflash, audit, manba nazorati — himoya tamoyillari
  4. Bog'liqliklarni jiddiy, xavfsizlik nuqtai nazaridan boshqaring

Nimani mustahkamlaydi: 2.1–2.8-bo'limlar.


Xulosa

Bu darsda pip bilan bog'liqliklarni professional boshqarishni o'rgandik.

Eng muhim uch fikr:

  1. Versiyalarni aniq belgilang. requirements.txt da faqat nom yozish (requests) kutilmagan yangilanish xavfini keltiradi — versiya oralig'i belgilang: requests>=2.31,<3.0. SemVer'da yangi asosiy versiya (3.0) API ni buzishi mumkin, shuning uchun yuqori chegara (<3.0) qo'shing. ~=2.31 (compatible release) — kichik versiyalarga ruxsat beradi, asosiyni cheklaydi (>=2.31,<3.0 ga teng).

  2. Takrorlanuvchanlik — retsept va qulf. requirements.txt git'ga qo'shiladi va loyihani boshqa kompyuterda takrorlash retseptidir. Qo'lda yozilgan requirements.txt oraliqlar (moslashuvchanlik), pip freeze esa aniq versiyalar (to'liq takrorlanuvchanlik) beradi. To'liq takrorlanuvchanlik uchun barcha (bilvosita ham) versiyalarni qulflang — pip freeze yoki lock fayl (poetry.lock, uv.lock).

  3. Bog'liqlik — xavfsizlik masalasi. Har paket o'z bog'liqliklariga ega (bog'liqlik daraxti), va ular to'qnashishi mumkin (A urllib3<2, B >=2). pip install PyPI dan istalgan kodni o'rnatadi va ishga tushiradi — nomni diqqat bilan tekshiring (typosquatting: reqeusts emas requests) va pip-audit bilan ma'lum zaifliklarni muntazam tekshiring. Yangilanishlarni testlar bilan sinab, keyin qabul qiling.

Keyingi darsda zamonaviy bog'liqlik boshqaruvchi vositalarni — poetry va uv ni o'rganamiz: ular muhit, bog'liqlik va qulflashni bitta vositada birlashtiradi va pip + venv ish oqimini soddalashtiradi.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
18.2-dars: pip va bog'liqliklar — IlmHamroh