Skip to content

Podział na Moduły i Paczki📦

Moduł - plik pythonowy zawierający definicje i wyrażenia, nazwa pliku jest nazwą modułu z dodanym rozszerzeniem .py (nazwa_modułu.py). Wewnątrz modułu ta nazwa jest dostępna jako zmienna globalna __name__.
Moduł jest jednym ze sposobów organizacji kodu w pythonie, na ogół w jednym module trzyma się blisko powiązane ze sobą definicje funkcji, klas etc.
Jeśli chodzi tu o grupowanie to warto zadbać tutaj o złoty środek (pliki nie muszą być duże, ani małe, muszą po prostu spójnie tworzyć logiczną całość).

Paczka - sposób na ustrukturyzowanie modułów ( pozwala to łatwo ustrukturyzować projekt)

Zarządzanie paczkami

Do instalacji można używać samodzielnych aplikacji pip (i pip3). (Ale w sytuacjach bardziej złożonych projektów warto rozważyć użycie innych menadżerów pakietów jak np UV)

pip3 install numpy

Można też wymusić od danej instancji pythona, aby zainstalował dla siebie daną paczkę (użyteczne gdy mamy wiele wersji).

python3 -m pip install numpy

PIP może też używać plików zawierających opisy paczek potrzebnych do zainstalowania requirements.txt

python3 -m pip install -r requirements.txt

gdzie plik moze wyglądać tak

# zsykłe paczki
pytest
pytest-cov

# Podawanie konkretnych paczek po sieci
http://my.package.repo/simple
git+ssh://git@git.example.com/MyProject

Tworzenie i używanie własnych paczek

Struktura projektu pythonowego

Przykładowe materiały od astral - Project structure and files oraz Guide to Python - Structuring Your Project

.
├── pyproject.toml
├── README.md
├── requirements-dev.txt
├── requirements.txt
├── src
│   └── package
│       ├── __init__.py
│       └── main.py
└── tests
    └── test_classes.py

Opisy poszczególnych plików:

  • requirements.txt - (teraz już nieco outdated) plik zawierający listę zależności projektu (instalowanych np. pip-em pip install -r requirements.txt)
  • pyproject.toml - oficjalnie zalecany plik konfiguracyjny projektu pythonowego. Zawiera on informacje o projekcie, konfiguracje dla narzędzi potrzebnych do jego budowy, testowania, formatowania kodu etc. Warto w nim umieszczać także requirementsy.

Przykładowy toml

[project]
name = "myproj_pythonowy"
version = "0.1.0"
authors = [{name = "Jan Kowalski", email = "jkowalski@email.pl"}]
readme = "README.md"
requires-python = ">=3.10"
description = "Mega fajny projekt"
dependencies = [
  "pyyaml",
  "jsonschema",
  "django > 2"
]

[project.optional-dependencies]
gui = ["PyQt5"]
cli = [
  "rich",
  "click",
]
dev = [
  # tests
  "pytest",
  "pytest-cov",
  # code-quality
  "mypy",
  "ruff",
]

[project.urls]
"Source" = https://strona.com

[project.scripts]
myproj = "myproj_pythonowy.__main__:main"

Paczkę instaluje się wtedy komendą: pip install ..
Paczkę + zależności deweloperskie instalujemy tutaj komendą pip install .[dev].

Struktura biblioteki

Przykładowa struktura paczki

sound/                          Top-level package
      __init__.py               Initialize the sound package
      formats/                  Subpackage for file format conversions
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  Subpackage for sound effects
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      filters/                  Subpackage for filters
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py
              ...

Aby wykorzystać zawartość pliku karaoke.py należy zaimportować:

import sound.filters.karaoke

Wewnętrzne linkowanie

Przy linkowaniu pomiędzy poszczególnymi elementami paczki zaleca się używanie poniższej konwencji:

#zakładamy, że jesteśmy w pliku filters/karaoke.py
from . import echo
from .. import formats
from ..filters import equalizer

Wczytywanie paczki z danego folderu

Kiedy nasza paczka jest w niestandardowym folderze można ją wczytać tak

#tu zakładam, że paczka jest umieszczona w jakimś folderze umieszczonym gdzieś względem pliku ze skryptem, ale module_path może być dowolne
module_path = os.path.dirname(os.path.realpath(__file__)) + "/.."
sys.path.append(module_path)