Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Modul va paket
- 2.2. __init__.py ning roli
- 2.3. Import turlari
- 2.4. src-layout vs tekis layout
- 2.5. Nima uchun src-layout afzal
- 2.6. Standart loyiha tuzilishi
- 2.7. Import muammolari
- 2.8. __main__.py va ishga tushirish
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Paket va modul tuzilishi
- Misol 2 — Import turlari (mutlaq va nisbiy)
- Misol 3 — src-layout va o'rnatish
- Misol 4 — Amaliy: loyiha skeletini qurish
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
19.1-dars: Loyiha tuzilishi
19-QISM — PAKETLASH VA CHIQARISH · 1-dars
1. Kirish va motivatsiya
Shu paytgacha kodni asosan bitta faylda yoki bir necha faylda yozdik. Kichik loyiha uchun bu yetarli, lekin kod o'sganda va uni boshqalar bilan ulashish (kutubxona yoki vosita sifatida) kerak bo'lganda, loyiha tuzilishi muhim ahamiyat kasb etadi. To'g'ri tuzilish kodni tashkil qiladi, import muammolarini oldini oladi va paketlashni (keyingi darslar) osonlashtiradi. Noto'g'ri tuzilish esa import xatolari, sinov muammolari va chalkashlikka olib keladi.
Professional Python loyihasi aniq, standart tuzilishga ega — kod, testlar, konfiguratsiya va hujjatlar o'z joyida.
Real vaziyat. Bir dasturchi foydali kutubxona yozdi va uni ulashmoqchi bo'ldi. Lekin barcha kod bitta papkada aralashib yotardi: manba kod, testlar, skriptlar, ma'lumot fayllari. Uni paketlashga uringanda muammolar chiqdi: testlar manba kodni import qila olmadi, pip install noto'g'ri fayllarni oldi, va "menda ishlaydi, o'rnatilgach yo'q" muammosi paydo bo'ldi — chunki kod o'rnatilgan paketni emas, mahalliy papkani import qilardi. U src-layout ga o'tdi: manba kod src/ da, testlar tests/ da, konfiguratsiya ildizda. Barcha muammolar yo'qoldi — tuzilish ularni oldindan oldini oldi.
Bu darsda professional loyiha tuzilishini o'rganamiz.
Bu darsda:
- Nima uchun tuzilish muhim
- Paket va modul (
__init__.py) - Import turlari (mutlaq va nisbiy)
-
src-layoutvs tekis (flat) layout - Standart loyiha tuzilishi
__init__.pyning roli- Keng tarqalgan import muammolari
- Amaliy: loyiha skeletini qurish
ℹ Misollarda paket tuzilishi vaqtinchalik papkada quriladi va import qilib tekshiriladi.
2. Nazariya — chuqur tushuntirish
2.1. Modul va paket
| Tushuncha | Nima |
|---|---|
| Modul | Bitta .py fayl |
| Paket | Modullar to'plami (papka + __init__.py) |
| Ost-paket | Paket ichidagi paket |
wisar/ # paket
__init__.py # paketni belgilaydi
core.py # modul
utils/ # ost-paket
__init__.py
matn.py # modul __init__.py fayli papkani paketga aylantiradi — Python uni import qilinadigan qiladi.
2.2. __init__.py ning roli
__init__.py paket import qilinganda bajariladi. U:
| Vazifa | Misol |
|---|---|
| Paketni belgilaydi | Bo'sh bo'lsa ham yetarli |
| Ommaviy API ni ochadi | from .core import salom |
| Versiyani saqlaydi | __version__ = "1.0.0" |
__all__ belgilaydi |
__all__ = ["salom"] |
# wisar/__init__.py
__version__ = "1.0.0"
from .core import salom # foydalanuvchi: from wisar import salom __init__.py — paketning "yuzi": foydalanuvchi nima ko'rishini belgilaydi.
2.3. Import turlari
| Tur | Sintaksis | Qachon |
|---|---|---|
| Mutlaq (absolute) | from wisar.core import salom |
Tavsiya etiladi |
| Nisbiy (relative) | from .core import salom |
Paket ichida |
| Nisbiy (yuqoriga) | from ..utils import katta |
Ota-paketdan |
# wisar/utils/matn.py ichida:
from wisar.core import salom # mutlaq — aniq
from ..core import salom # nisbiy — qisqaMutlaq importlar aniqroq va ishonchli; nisbiy importlar paket ichida qisqaroq. Ko'p uslub qo'llanmasi mutlaq importlarni afzal ko'radi.
2.4. src-layout vs tekis layout
Tekis (flat) layout:
loyiha/
wisar/ # paket to'g'ridan-to'g'ri ildizda
__init__.py
core.py
tests/
pyproject.tomlsrc-layout (tavsiya):
loyiha/
src/
wisar/ # paket src/ ichida
__init__.py
core.py
tests/
pyproject.toml src-layout afzalligi: testlar o'rnatilgan paketni import qiladi (mahalliy papkani emas), shuning uchun "o'rnatilgach ishlamaydi" muammosi oldindan ushlanadi.
2.5. Nima uchun src-layout afzal
| Muammo (tekis) | src-layout yechimi |
|---|---|
| Test mahalliy papkani import qiladi | O'rnatilgan paketni import qiladi |
| "O'rnatilgach yo'q" jim o'tadi | Erta ushlanadi |
Joriy papka sys.path da |
Aralashuv yo'q |
| Tasodifan noto'g'ri fayl | Aniq chegara |
Tekis layout oddiyroq va kichik loyiha uchun yaxshi; src-layout paketlanadigan, jiddiy loyihalar uchun.
2.6. Standart loyiha tuzilishi
loyiha/
src/
wisar/
__init__.py
core.py
utils/
__init__.py
tests/
test_core.py
docs/ # hujjatlar (19.7)
pyproject.toml # konfiguratsiya (19.2)
README.md # tavsif
LICENSE # litsenziya (19.8)
.gitignore| Element | Vazifa |
|---|---|
src/paket/ |
Manba kod |
tests/ |
Testlar |
pyproject.toml |
Metama'lumot, bog'liqliklar |
README.md |
Loyiha tavsifi |
LICENSE |
Foydalanish shartlari |
2.7. Import muammolari
| Muammo | Sabab | Yechim |
|---|---|---|
ModuleNotFoundError |
Paket sys.path da yo'q |
O'rnating (pip install -e .) |
ImportError: attempted relative import |
Nisbiy import to'g'ridan-to'g'ri ishga tushirildi | Paket sifatida ishga tushiring (python -m) |
| Test import qila olmaydi | Noto'g'ri tuzilish | src-layout + pip install -e . |
| Aylanma import (circular) | A B ni, B A ni import qiladi | Tuzilmani qayta ko'ring |
pip install -e . (editable) — loyihani "tahrirlanadigan" holatda o'rnatadi: kod o'zgarishlari darhol ko'rinadi, lekin import to'g'ri ishlaydi.
2.8. __main__.py va ishga tushirish
Paketni to'g'ridan-to'g'ri ishga tushirish uchun __main__.py:
wisar/
__init__.py
__main__.py # python -m wisar bilan ishga tushadi# wisar/__main__.py
from wisar.core import main
main()python -m wisar # __main__.py ni ishga tushiradi python -m paket — paketni to'g'ri, sys.path muammolarisiz ishga tushiradi.
3. Tez ma'lumotnoma
loyiha/
src/paket/
__init__.py # __version__, ommaviy API
core.py
__main__.py # python -m paket
tests/
pyproject.toml
README.md, LICENSE# __init__.py
__version__ = "1.0.0"
from .core import salom # ommaviy API
# import turlari:
from paket.core import salom # mutlaq (tavsiya)
from .core import salom # nisbiy (paket ichida)Qoidalar
paket = papka + __init__.py
src-layout — paketlanadigan loyiha uchun
mutlaq importlar — aniqroq
pip install -e . — tahrirlanadigan o'rnatish
python -m paket — to'g'ri ishga tushirish
testlar tests/ da, kod src/ da4. Batafsil misollar
Misollarda paket tuzilishi vaqtinchalik papkada quriladi va import qilib tekshiriladi.
Misol 1 — Paket va modul tuzilishi
"""paket = papka + __init__.py; modul = .py fayl; ost-paket; __init__.py ommaviy API va versiyani ochadi; import qilib tekshirish."""
import subprocess
import sys
import tempfile
from pathlib import Path
def main() -> None:
with tempfile.TemporaryDirectory() as katalog:
r = Path(katalog)
paket = r / "wisar"
(paket / "utils").mkdir(parents=True)
# __init__.py — ommaviy API va versiya
(paket / "__init__.py").write_text(
'__version__ = "1.0.0"\nfrom .core import salom\n', encoding="utf-8")
(paket / "core.py").write_text(
'def salom(ism):\n return f"Salom, {ism}!"\n', encoding="utf-8")
(paket / "utils" / "__init__.py").write_text(
'from .matn import katta\n', encoding="utf-8")
(paket / "utils" / "matn.py").write_text(
'def katta(s):\n return s.upper()\n', encoding="utf-8")
print("=== 1. Tuzilish ===")
for yol in sorted(paket.rglob("*.py")):
print(f" {yol.relative_to(r).as_posix()}")
print("\n=== 2. Import qilib tekshirish ===")
kod = (
"import wisar\n"
"print('version:', wisar.__version__)\n"
"print(wisar.salom('Aziz'))\n"
"from wisar.utils import katta\n"
"print('katta:', katta('salom'))\n"
"print('paket (has __path__):', hasattr(wisar, '__path__'))\n"
)
natija = subprocess.run([sys.executable, "-c", kod], cwd=r, capture_output=True, text=True, encoding="utf-8")
for qator in natija.stdout.splitlines():
print(f" {qator}")
print("\n=== 3. __init__.py roli ===")
print(" __init__.py papkani PAKETga aylantiradi")
print(" __version__ va 'from .core import salom' — ommaviy API")
print(" ⭐ foydalanuvchi: 'from wisar import salom' (core ichida ekanini bilmaydi)")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Tuzilish ===
wisar/__init__.py
wisar/core.py
wisar/utils/__init__.py
wisar/utils/matn.py
=== 2. Import qilib tekshirish ===
version: 1.0.0
Salom, Aziz!
katta: SALOM
paket (has __path__): True
=== 3. __init__.py roli ===
__init__.py papkani PAKETga aylantiradi
__version__ va 'from .core import salom' — ommaviy API
⭐ foydalanuvchi: 'from wisar import salom' (core ichida ekanini bilmaydi)Nima ko'rsatdi: 2.1, 2.2-bo'limlar.
Misol 2 — Import turlari (mutlaq va nisbiy)
"""mutlaq (from paket.core import) va nisbiy (from .core import) importlar; ikkalasi ham ishlaydi; nisbiy faqat paket ichida; python -m bilan ishga tushirish."""
import subprocess
import sys
import tempfile
from pathlib import Path
def main() -> None:
with tempfile.TemporaryDirectory() as katalog:
r = Path(katalog)
paket = r / "wisar"
paket.mkdir()
(paket / "__init__.py").write_text("", encoding="utf-8")
(paket / "core.py").write_text('KOEFF = 10\n', encoding="utf-8")
# mutlaq import ishlatadigan modul
(paket / "mutlaq.py").write_text(
'from wisar.core import KOEFF\n'
'def hisobla(x):\n return x * KOEFF\n', encoding="utf-8")
# nisbiy import ishlatadigan modul
(paket / "nisbiy.py").write_text(
'from .core import KOEFF\n'
'def hisobla(x):\n return x * KOEFF\n', encoding="utf-8")
print("=== 1. Mutlaq import (from wisar.core import) ===")
kod = "from wisar.mutlaq import hisobla\nprint('mutlaq:', hisobla(5))\n"
natija = subprocess.run([sys.executable, "-c", kod], cwd=r, capture_output=True, text=True, encoding="utf-8")
print(f" {natija.stdout.strip()}")
print("\n=== 2. Nisbiy import (from .core import) ===")
kod = "from wisar.nisbiy import hisobla\nprint('nisbiy:', hisobla(5))\n"
natija = subprocess.run([sys.executable, "-c", kod], cwd=r, capture_output=True, text=True, encoding="utf-8")
print(f" {natija.stdout.strip()}")
print("\n=== 3. ⚠️ Nisbiy importni to'g'ridan-to'g'ri ishga tushirish ===")
natija = subprocess.run([sys.executable, str(paket / "nisbiy.py")], capture_output=True, text=True, encoding="utf-8")
xato_bor = "ImportError" in natija.stderr or "attempted relative" in natija.stderr
print(f" 'python nisbiy.py' xato beradi: {xato_bor}")
print(" ⭐ nisbiy import faqat paket sifatida ishlaydi (python -m wisar.nisbiy)")
print("\n=== 4. Xulosa ===")
print(" mutlaq (from wisar.core): aniq, har joyda ishlaydi — tavsiya")
print(" nisbiy (from .core): qisqa, faqat paket ichida")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Mutlaq import (from wisar.core import) ===
mutlaq: 50
=== 2. Nisbiy import (from .core import) ===
nisbiy: 50
=== 3. ⚠️ Nisbiy importni to'g'ridan-to'g'ri ishga tushirish ===
'python nisbiy.py' xato beradi: True
⭐ nisbiy import faqat paket sifatida ishlaydi (python -m wisar.nisbiy)
=== 4. Xulosa ===
mutlaq (from wisar.core): aniq, har joyda ishlaydi — tavsiya
nisbiy (from .core): qisqa, faqat paket ichidaNima ko'rsatdi: 2.3-bo'lim.
Misol 3 — src-layout va o'rnatish
"""src-layout: paket src/ ichida; tekis layout bilan farq; nima uchun src-layout testlar uchun ishonchliroq; tuzilish namunasi."""
import subprocess
import sys
import tempfile
from pathlib import Path
def main() -> None:
with tempfile.TemporaryDirectory() as katalog:
r = Path(katalog)
print("=== 1. src-layout tuzilishi ===")
(r / "src" / "wisar").mkdir(parents=True)
(r / "tests").mkdir()
(r / "src" / "wisar" / "__init__.py").write_text('from .core import salom\n', encoding="utf-8")
(r / "src" / "wisar" / "core.py").write_text('def salom(ism):\n return f"Salom, {ism}!"\n', encoding="utf-8")
(r / "tests" / "test_core.py").write_text('from wisar import salom\ndef test_salom():\n assert salom("Aziz") == "Salom, Aziz!"\n', encoding="utf-8")
(r / "pyproject.toml").write_text('[project]\nname = "wisar"\nversion = "1.0.0"\n', encoding="utf-8")
(r / "README.md").write_text("# Wisar\n", encoding="utf-8")
for yol in sorted(r.rglob("*")):
if yol.is_file():
print(f" {yol.relative_to(r).as_posix()}")
print("\n=== 2. src-layout bilan import (src yo'lda) ===")
kod = "import sys; sys.path.insert(0, 'src')\nfrom wisar import salom\nprint(salom('Aziz'))\n"
natija = subprocess.run([sys.executable, "-c", kod], cwd=r, capture_output=True, text=True, encoding="utf-8")
print(f" {natija.stdout.strip()}")
print("\n=== 3. Tekis vs src-layout ===")
print(" tekis: loyiha/wisar/ — paket ildizda, joriy papka sys.path'da")
print(" src: loyiha/src/wisar/ — paket src/ ichida, aralashuv yo'q")
print(" ⭐ src-layout: testlar O'RNATILGAN paketni import qiladi (mahalliy emas)")
print(" ⭐ 'o'rnatilgach ishlamaydi' muammosi oldindan ushlanadi")
print("\n=== 4. pip install -e . g'oyasi ===")
print(" 'pip install -e .' — tahrirlanadigan o'rnatish")
print(" kod o'zgarishlari darhol ko'rinadi, LEKIN import to'g'ri ishlaydi")
print(" ⭐ rivojlanishda qulay, tuzilish to'g'ri")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. src-layout tuzilishi ===
pyproject.toml
README.md
src/wisar/__init__.py
src/wisar/core.py
tests/test_core.py
=== 2. src-layout bilan import (src yo'lda) ===
Salom, Aziz!
=== 3. Tekis vs src-layout ===
tekis: loyiha/wisar/ — paket ildizda, joriy papka sys.path'da
src: loyiha/src/wisar/ — paket src/ ichida, aralashuv yo'q
⭐ src-layout: testlar O'RNATILGAN paketni import qiladi (mahalliy emas)
⭐ 'o'rnatilgach ishlamaydi' muammosi oldindan ushlanadi
=== 4. pip install -e . g'oyasi ===
'pip install -e .' — tahrirlanadigan o'rnatish
kod o'zgarishlari darhol ko'rinadi, LEKIN import to'g'ri ishlaydi
⭐ rivojlanishda qulay, tuzilish to'g'riNima ko'rsatdi: 2.4, 2.5, 2.7-bo'limlar.
Misol 4 — Amaliy: loyiha skeletini qurish
To'liq professional loyiha skeletini yaratuvchi skript yozamiz: src-layout, testlar, konfiguratsiya, __main__.py, README va boshqalar. Bu — yangi paketlanadigan loyiha boshlashning standart tuzilishi.
"""to'liq loyiha skeleti: src-layout, __init__.py (versiya+API), __main__.py, tests/, pyproject.toml, README; import va python -m bilan tekshirish."""
import subprocess
import sys
import tempfile
from pathlib import Path
def loyiha_yarat(ildiz: Path, nom: str) -> None:
paket = ildiz / "src" / nom
(paket / "utils").mkdir(parents=True)
(ildiz / "tests").mkdir()
(paket / "__init__.py").write_text(
f'"""{nom} — Wisar namunaviy paketi."""\n'
f'__version__ = "0.1.0"\n'
f'from .core import salomla\n', encoding="utf-8")
(paket / "core.py").write_text(
'def salomla(ism: str) -> str:\n return f"Salom, {ism}!"\n', encoding="utf-8")
(paket / "__main__.py").write_text(
f'from {nom}.core import salomla\n'
'import sys\n'
'ism = sys.argv[1] if len(sys.argv) > 1 else "dunyo"\n'
'print(salomla(ism))\n', encoding="utf-8")
(paket / "utils" / "__init__.py").write_text("", encoding="utf-8")
(paket / "utils" / "matn.py").write_text('def katta(s: str) -> str:\n return s.upper()\n', encoding="utf-8")
(ildiz / "tests" / "test_core.py").write_text(
f'from {nom} import salomla\ndef test_salomla():\n assert salomla("Aziz") == "Salom, Aziz!"\n', encoding="utf-8")
(ildiz / "pyproject.toml").write_text(
f'[project]\nname = "{nom}"\nversion = "0.1.0"\nrequires-python = ">=3.11"\n', encoding="utf-8")
(ildiz / "README.md").write_text(f"# {nom}\n\nWisar namunaviy paketi.\n", encoding="utf-8")
(ildiz / ".gitignore").write_text(".venv/\n__pycache__/\n*.pyc\ndist/\n", encoding="utf-8")
def main() -> None:
with tempfile.TemporaryDirectory() as katalog:
r = Path(katalog)
loyiha_yarat(r, "wisar")
print("=== 1. Yaratilgan tuzilish ===")
for yol in sorted(r.rglob("*")):
if yol.is_file():
print(f" {yol.relative_to(r).as_posix()}")
print("\n=== 2. Paketni import qilish ===")
kod = "import sys; sys.path.insert(0, 'src')\nimport wisar\nprint('version:', wisar.__version__)\nprint(wisar.salomla('Aziz'))\n"
natija = subprocess.run([sys.executable, "-c", kod], cwd=r, capture_output=True, text=True, encoding="utf-8")
for qator in natija.stdout.splitlines():
print(f" {qator}")
print("\n=== 3. python -m wisar bilan ishga tushirish ===")
env = {"PYTHONPATH": str(r / "src")}
import os
env2 = {**os.environ, **env}
natija = subprocess.run([sys.executable, "-m", "wisar", "Bek"], cwd=r, capture_output=True, text=True, encoding="utf-8", env=env2)
print(f" chiqish: {natija.stdout.strip()}")
print("\n=== 4. Skelet elementlari ===")
print(" src/wisar/ — manba kod; tests/ — testlar")
print(" __init__.py — versiya+API; __main__.py — python -m")
print(" pyproject.toml — metama'lumot 19.2-bob; README, LICENSE, .gitignore")
print(" ⭐ standart tuzilish — paketlash 19.3-bob va nashr 19.4-bob uchun tayyor")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Yaratilgan tuzilish ===
.gitignore
pyproject.toml
README.md
src/wisar/__init__.py
src/wisar/__main__.py
src/wisar/core.py
src/wisar/utils/__init__.py
src/wisar/utils/matn.py
tests/test_core.py
=== 2. Paketni import qilish ===
version: 0.1.0
Salom, Aziz!
=== 3. python -m wisar bilan ishga tushirish ===
chiqish: Salom, Bek!
=== 4. Skelet elementlari ===
src/wisar/ — manba kod; tests/ — testlar
__init__.py — versiya+API; __main__.py — python -m
pyproject.toml — metama'lumot 19.2-bob; README, LICENSE, .gitignore
⭐ standart tuzilish — paketlash 19.3-bob va nashr 19.4-bob uchun tayyorNima ko'rsatdi: 2.6, 2.8-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "Barcha kodni bitta papkaga" | Tuzilish import va paketlash uchun muhim |
"__init__.py shart emas" |
Papkani paketga aylantiradi (implicit paketlar cheklovli) |
| "Nisbiy import har doim yaxshi" | Mutlaq importlar aniqroq |
"src-layout ortiqcha" |
Testlar uchun ishonchliroq |
| "Test kodni to'g'ridan import qiladi" | pip install -e . bilan o'rnating |
"python fayl.py har doim ishlaydi" |
Nisbiy importda xato |
| "Tuzilish keyin tuzatiladi" | Boshdan to'g'ri qilish oson |
"__main__.py keraksiz" |
python -m paket uchun |
6. Keng tarqalgan xatolar va yechimlari
1. Hamma narsa bitta papkada
loyiha/*.py # ❌ kod, test, skript aralash
loyiha/src/paket/, tests/ # ✅ ajratilgan2. __init__.py siz papka
paket/core.py # ⚠️ implicit paket (muammoli)
paket/__init__.py, core.py # ✅ aniq paket3. Nisbiy importni to'g'ridan ishga tushirish
python paket/modul.py # ❌ ImportError (nisbiy import)
python -m paket.modul # ✅4. Test o'rnatilmagan paketni import
# tests/ manba kodni topa olmaydi # ❌
pip install -e . # ✅ tahrirlanadigan o'rnatish5. sys.path ni qo'lda o'zgartirish
sys.path.insert(0, "../src") # ❌ mo'rt
pip install -e . # ✅ to'g'ri o'rnatish6. Aylanma import
# a.py: from b import x; b.py: from a import y # ❌ circular
# ✅ umumiy kodni uchinchi modulga ajrating7. __init__.py da og'ir kod
# __init__.py da katta hisob # ⚠️ import sekinlashtiradi
# ✅ faqat API ni oching, hisobni funksiyada7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 18.1–18.3-darslar (o'tilgan): venv, pip — loyiha muhiti
- 19.2-dars:
pyproject.toml— loyiha metama'lumoti - 19.3-dars: paket yig'ish — bu tuzilishdan
- 17.3-dars (o'tilgan): fixture, testlar —
tests/papkasi - 27-qism: arxitektura — katta loyiha tuzilishi
8. Eng yaxshi amaliyotlar
src-layoutishlating (paketlanadigan loyiha uchun).Har paketda
__init__.py— ommaviy API va versiyani oching.Mutlaq importlarni afzal ko'ring (aniqroq).
Testlarni
tests/da,pip install -e .bilan o'rnating.python -m paketuchun__main__.pyqo'shing.Kod, test, konfiguratsiya, hujjatlarni ajrating.
Aylanma importlardan qoching (tuzilmani qayta ko'ring).
Loyihani boshidan to'g'ri tuzilishda boshlang.
9. Amaliy topshiriq
Vazifa 1: Bashorat qiling
1. # papkani paketga nima aylantiradi?
2. # modul nima?
3. # 'from .core import x' qaysi import turi?
4. # 'from paket.core import x' qaysi tur?
5. # src-layout da paket qayerda?
6. # __init__.py da __version__ nima uchun?
7. # python -m paket qaysi faylni ishga tushiradi?
8. # 'python paket/modul.py' nisbiy importda nima bo'ladi?
9. # pip install -e . nima qiladi?
10. # tests/ papkasi nima uchun?
11. # __init__.py bo'sh bo'lsa ishlaydimi?
12. # mutlaq import afzalligimi yoki nisbiy?Javoblar
__init__.pyfayli- Bitta
.pyfayl - Nisbiy (relative)
- Mutlaq (absolute)
src/papkasida- Paket versiyasini saqlash uchun
__main__.pyImportError(attempted relative import)- Loyihani tahrirlanadigan holatda o'rnatadi
- Testlar uchun (koddan ajratilgan)
- Ha — papkani paketga aylantiradi
- Mutlaq (aniqroq, ishonchli)
Vazifa 2: Xatolarni tuzating
1. loyiha/
main.py
test.py
utils.py
ma'lumot.csv # hammasi aralash
2. paket/
core.py # __init__.py yo'q
3. # nisbiy import ishga tushirish:
python paket/modul.py
4. # test:
import sys
sys.path.insert(0, "../src") # qo'lda path
5. # a.py: from b import x
# b.py: from a import y # aylanmaJavoblar
1. loyiha/
src/paket/
__init__.py
core.py
utils.py
tests/test_core.py
data/malumot.csv # ajratilgan
2. paket/
__init__.py # qo'shildi
core.py
3. python -m paket.modul # paket sifatida
4. pip install -e . # sys.path emas, o'rnatish
5. # umumiy.py ga x, y ni ajrating
# a.py: from umumiy import x
# b.py: from umumiy import yVazifa 3: Loyiha skeleti
loyiha_yarat(nom) skripti:
src-layout,tests/,pyproject.toml,README.md,LICENSE,.gitignore__init__.py(versiya+API),__main__.py- Namunaviy modul va test
- Import va
python -mbilan tekshiring
Vazifa 4: Import tahlili
Loyihadagi importlarni tahlil qiling:
- Mutlaq va nisbiy importlarni sanang
- Aylanma importlarni toping
- Ishlatilmagan importlarni (18.4, ruff) toping
- Nisbiylarni mutlaqqa aylantiring
Vazifa 5: __init__.py dizayni
Paket uchun __init__.py:
- Ommaviy API ni aniqlang (
from .core import ...) __all__bilan eksportni belgilang__version__qo'shing- Ichki (
_yashirin) modullarni yashiring
Vazifa 6: src-layout migratsiya
Tekis layout loyihani src-layout ga:
- Paketni
src/ga ko'chiring - Testlarni yangilang
pyproject.tomlni sozlang- Import va testlar ishlashini tasdiqlang
Vazifa 7: O'ylash
src-layout uzoq bahs mavzusi bo'lgan: ba'zi dasturchilar uni "ortiqcha murakkablik" deb hisoblaydi, boshqalari "yagona to'g'ri yo'l" deydi. Nima uchun tuzilish tanlovi shunchalik muhim va bahsli, va "kelishuv ustidan aniqlik" (convention over configuration) tamoyili loyiha tuzilishida qanday namoyon bo'ladi?
Javob
Qisqa javob: Tuzilish tanlovi bahsli, chunki u oddiylik (tekis — kam papka) va ishonchlilik (src — muammolarni oldindan ushlaydi) orasidagi muvozanat. Kichik loyihada tekis yetarli, katta/paketlanadiganda src afzal. "Kelishuv ustidan aniqlik" (convention over configuration) — standart tuzilishga amal qilib, vositalar (test, build, IDE) uni avtomatik tushunishi. Standart tuzilish qaror yukini kamaytiradi va vositalar ekotizimiga mos keladi.
1. Nega tuzilish muhim
| Sabab | Tafsilot |
|---|---|
| Import to'g'riligi | Noto'g'ri tuzilish — import xatolari |
| Paketlash | Vositalar standart tuzilishni kutadi |
| Test ishonchliligi | src — o'rnatilgan paketni sinaydi |
| Yangi a'zoga oson | Standart — tanish |
| Vosita mosligi | IDE, build, test avtomatik tushunadi |
2. Tekis vs src bahsi
| Tekis afzalligi | src afzalligi |
|---|---|
| Oddiyroq (kam papka) | Test o'rnatilgan paketni sinaydi |
| Kichik loyiha uchun yaxshi | "O'rnatilgach yo'q" ni ushlaydi |
| Kam ko'chirish | Aniq chegara |
| Tez boshlash | Jiddiy loyiha uchun ishonchli |
3. "Kelishuv ustidan aniqlik"
| Tamoyil | Loyiha tuzilishida |
|---|---|
| Standart tuzilish | src/, tests/, pyproject.toml |
| Vositalar tushunadi | pytest, build, IDE avtomatik |
| Kam sozlash | Standartga amal qil — sozlash shart emas |
| Bashoratlilik | Har loyiha tanish ko'rinadi |
4. Muvozanat
| Loyiha | Tavsiya |
|---|---|
| Kichik skript | Bitta fayl yoki tekis |
| O'rta kutubxona | Tekis yoki src |
| Paketlanadigan/jiddiy | src-layout |
| Katta jamoa | Standart (src) muhim |
5. Muhandislik saboqlari
- Tuzilish — texnik va ijtimoiy qaror (jamoa uchun)
- Standartlar qaror yukini kamaytiradi
- Vositalar ekotizimiga moslik muhim
- Oddiylik va ishonchlilik muvozanati
6. Xulosa
- Tuzilish import, paketlash, test uchun muhim
- Tekis — oddiy, src — ishonchli
- "Kelishuv ustidan aniqlik" — standart tuzilish
- Loyiha kattaligiga qarab tanlang
Nimani mustahkamlaydi: 2.1–2.8-bo'limlar.
Xulosa
Bu darsda professional loyiha tuzilishini o'rgandik.
Eng muhim uch fikr:
Paket = papka +
__init__.py. Modul — bitta.pyfayl, paket — modullar to'plami (__init__.pyfayli papkani paketga aylantiradi).__init__.pypaketning "yuzi": ommaviy API ni ochadi (from .core import salom), versiyani saqlaydi (__version__) — foydalanuvchifrom wisar import salomyozadi, kodcoreichida ekanini bilmaydi. Mutlaq importlar (from wisar.core import ...) aniqroq va ishonchli; nisbiy (from .core import ...) paket ichida qisqaroq.src-layout— paketlanadigan loyiha uchun. Tekis layoutda paket ildizda (loyiha/wisar/),src-layoutda esasrc/ichida (loyiha/src/wisar/).src-layoutafzalligi: testlar o'rnatilgan paketni import qiladi (mahalliy papkani emas), shuning uchun "o'rnatilgach ishlamaydi" muammosi oldindan ushlanadi.pip install -e .(editable) loyihani tahrirlanadigan holatda o'rnatadi — kod o'zgarishlari darhol ko'rinadi, import to'g'ri ishlaydi.Standart tuzilish va ishga tushirish. Professional loyiha:
src/paket/(kod),tests/(testlar),pyproject.toml(metama'lumot),README.md,LICENSE,.gitignore.__main__.pybilan paketnipython -m paketorqali to'g'ri (sys.pathmuammolarisiz) ishga tushirasiz. Nisbiy importni to'g'ridan-to'g'ri ishga tushirish (python paket/modul.py) xato beradi — paket sifatida (python -m) ishga tushiring. "Kelishuv ustidan aniqlik" — standart tuzilishga amal qilib, vositalar (test, build, IDE) uni avtomatik tushunadi.
Keyingi darsda loyiha metama'lumotini — pyproject.toml ni chuqurroq o'rganamiz: paket nomi, versiya, bog'liqliklar, kirish nuqtalari va build tizimini sozlash.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!