Moduły i pakiety w Pythonie – organizacja kodu

Kacper Sieradziński
Kacper Sieradziński
15 marca 2025Edukacja3 min czytania

W miarę jak projekt w Pythonie rośnie, rośnie też chaos. Kilkaset linii kodu w jednym pliku to przepis na bałagan: trudne debugowanie, powtarzający się kod, brak możliwości ponownego użycia funkcji. Rozwiązaniem są modułypakiety – mechanizm, który pozwala dzielić projekt na logiczne części i zachować porządek.

Obraz główny Moduły i pakiety w Pythonie – organizacja kodu

W tym artykule pokażę Ci:

  • czym różni się moduł od pakietu,
  • jak poprawnie organizować strukturę katalogów,
  • jak działają importy,
  • oraz jak przygotować kod do ponownego wykorzystania w innych projektach.

Czym jest moduł w Pythonie?

Moduł to po prostu plik .py, który zawiera kod Pythona: funkcje, klasy, zmienne lub stałe.

Przykład prostego modułu:

Python
1 2 3 4 5 6 # plik math_utils.py def add(a, b): return a + b def multiply(a, b): return a * b

Ten plik możesz zaimportować w innym miejscu:

Python
1 2 3 import math_utils print(math_utils.add(2, 3))

Możesz też zaimportować konkretne elementy:

Python
1 2 from math_utils import add print(add(5, 7))

Moduły pomagają:

  • unikać duplikacji kodu,
  • skracać pliki źródłowe,
  • łatwiej testować poszczególne elementy aplikacji.

Czym jest pakiet w Pythonie?

Pakiet to folder, który zawiera wiele modułów (plików .py) i plik __init__.py. To właśnie ten plik sprawia, że Python rozpoznaje katalog jako pakiet.

Przykład struktury pakietu:

Bash
1 2 3 4 5 6 7 project/ │ ├── main.py └── utils/ ├── __init__.py ├── math_utils.py └── string_utils.py

Dzięki temu możesz pisać:

Python
1 2 from utils.math_utils import add from utils.string_utils import capitalize_text

Co robi __init__.py?

Plik __init__.py może być pusty – ale nie musi. Możesz w nim definiować, które elementy pakietu mają być widoczne po imporcie:

Python
1 2 3 # utils/__init__.py from .math_utils import add from .string_utils import capitalize_text

Wtedy użytkownik może pisać:

Python
1 from utils import add, capitalize_text

Struktura projektu w Pythonie

Dobra organizacja kodu to nie przypadek. W większych projektach Pythonowych warto stosować jednolitą strukturę katalogów.

Przykład poprawnej struktury

Bash
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 my_project/ │ ├── my_project/ │ ├── __init__.py │ ├── main.py │ ├── config.py │ ├── utils/ │ │ ├── __init__.py │ │ ├── math_utils.py │ │ └── file_utils.py │ └── models/ │ ├── __init__.py │ └── user.py │ ├── tests/ │ ├── test_math_utils.py │ └── test_user.py │ ├── requirements.txt └── README.md

Taka organizacja:

  • rozdziela logikę aplikacji (my_project/) od testów (tests/),
  • grupuje powiązane funkcjonalności w folderach (utils, models),
  • ułatwia automatyczne testowanie i deployment.

Jak działa import w Pythonie?

Mechanizm importu to kluczowy element zrozumienia modułów. Python szuka modułów w określonych lokalizacjach, które możesz sprawdzić:

Python
1 2 import sys print(sys.path)

To lista katalogów, w których interpreter szuka plików .py. Jeśli Twój moduł nie znajduje się w tych lokalizacjach, Python zwróci błąd ModuleNotFoundError.

Importy względne i bezwzględne

  • Import bezwzględny: podajesz pełną ścieżkę pakietu od katalogu głównego projektu.
Python
1 from my_project.utils.math_utils import add
  • Import względny: działa wewnątrz pakietu, używając kropki (.).
Python
1 2 from .math_utils import add from ..models.user import User

Importy względne przydają się, gdy pracujesz wewnątrz pakietów, a nie chcesz twardo wiązać ścieżek z głównym katalogiem projektu.

Najczęstsze błędy przy organizacji kodu

1. Brak pliku __init__.py

Bez tego pliku Python nie rozpozna folderu jako pakietu. Efekt: ModuleNotFoundError, mimo że ścieżka wygląda poprawnie.

2. Zagnieżdżone importy cykliczne

Błąd występuje, gdy dwa moduły importują się nawzajem. Zamiast:

Python
1 2 3 4 5 # user.py from utils import validate_email # utils.py from user import User

Zrób tak:

  • przenieś wspólny kod do trzeciego modułu,
  • importuj tylko w jednym kierunku.

3. Nadpisywanie nazw modułów

Jeśli nazwiesz plik random.py lub json.py, zasłonisz standardową bibliotekę. To klasyczny błąd początkujących – unikaj nazw pokrywających się z modułami Pythona.

Tworzenie własnych pakietów do ponownego użycia

Jeśli Twój pakiet jest uniwersalny, możesz przygotować go do ponownego użycia w innych projektach.

Struktura:

Bash
1 2 3 4 5 6 7 8 9 my_package/ │ ├── my_package/ │ ├── __init__.py │ ├── core.py │ ├── helpers.py │ ├── setup.py └── README.md

Przykładowy setup.py:

Python
1 2 3 4 5 6 7 8 from setuptools import setup, find_packages setup( name='my_package', version='0.1.0', packages=find_packages(), install_requires=[], )

Instalacja lokalna:

Bash
1 pip install -e .

Dzięki temu możesz używać swojego pakietu w dowolnym projekcie, pisząc:

Python
1 from my_package import core

Dobre praktyki organizacji kodu

  1. Jedna odpowiedzialność na moduł – nie mieszaj logiki, danych i widoków w jednym pliku.
  2. Nazwy folderów i plików w lowercase – zgodnie z PEP 8.
  3. Testy w osobnym katalogu – najlepiej równoległym do folderu z kodem źródłowym.
  4. Unikaj importów „gwiazdkowych" (from module import *) – obniżają czytelność.
  5. Zachowuj spójność nazw – jeśli masz user.py, trzymaj się tej konwencji (nie users.py w jednym miejscu i user_model.py w innym).

Podsumowanie

Organizacja kodu w Pythonie to nie tylko kwestia estetyki, ale też skalowalności. Moduły i pakiety pozwalają budować projekty, które rosną bez bólu głowy – łatwiej je testować, rozwijać i utrzymywać.

Jeśli tworzysz własne aplikacje, zacznij już teraz dzielić kod na moduły i porządnie układać strukturę katalogów. To inwestycja, która zwróci się przy pierwszym poważnym refaktoryzowaniu projektu.

Umiejętność organizacji kodu w moduły jest kluczowa w projektach webowych. Dowiedz się, jak Django i Flask wykorzystują te koncepcje w web development z Pythonie.