2. Środowiska i Narzędzia: Profesjonalne Zarządzanie Projektem¶
Note
Opanowanie narzędzi do zarządzania środowiskiem i zależnościami jest tak samo ważne, jak znajomość składni języka. W Pythonie, gdzie ekosystem bibliotek jest ogromny, izolacja zależności projektowych jest absolutnie kluczowa dla utrzymania porządku i zapewnienia reprodukowalności.
Podatek dziesięciu narzędzi¶
Deweloper przychodzący z C#/Java oczekuje jednego, spójnego toolingu: dotnet lub cargo/mvn robią praktycznie wszystko. W Pythonie przez lata było inaczej. Tradycyjny, „klasyczny" stos to około jedenastu osobnych narzędzi, które trzeba zainstalować, skonfigurować i utrzymać w spójności wersji w całym zespole - zanim napiszesz pierwszą linijkę kodu produkcyjnego:
| # | Narzędzie | Odpowiedzialność |
|---|---|---|
| 01 | pip |
instalacja pakietów |
| 02 | venv |
środowiska wirtualne |
| 03 | pyenv |
zarządzanie wersjami Pythona |
| 04 | pipx |
instalacja narzędzi globalnych |
| 05 | poetry |
zarządzanie projektem i plik lock |
| 06 | black |
formatowanie kodu |
| 07 | isort |
sortowanie importów |
| 08 | flake8 |
podstawowy linting |
| 09 | pylint |
głęboka analiza statyczna |
| 10 | bandit |
analiza bezpieczeństwa |
| 11 | mypy |
kontrola typów |
Każde z tych narzędzi ma własny plik konfiguracyjny i własny cykl wydawniczy. To jedenaście niezależnych miejsc, w których wersje mogą się rozjechać między laptopem juniora, laptopem seniora a CI - i jedenaście rzeczy, które nowa osoba w zespole musi poprawnie skonfigurować, zanim cokolwiek zadziała.
Współczesny ekosystem (stan na maj 2026) redukuje ten stos do dwóch narzędzi - uv + ruff - a wkrótce do trzech (po dodaniu ty). Wszystkie pochodzą od jednej firmy (Astral), wszystkie napisano w Rust, wszystkie czytają jeden plik konfiguracyjny pyproject.toml i ze sobą współpracują.
Tip
Trzy narzędzia, które ze sobą nie walczą, zastępują jedenaście, które walczyły.
flowchart LR
subgraph OLD["Klasyczny stos (~11 narzędzi)"]
direction TB
T1["pip"]
T2["venv"]
T3["pyenv"]
T4["pipx"]
T5["poetry"]
T6["black"]
T7["isort"]
T8["flake8"]
T9["pylint"]
T10["bandit"]
T11["mypy"]
end
subgraph NEW["Nowoczesny stos (Astral, Rust)"]
direction TB
U["uv<br/>(pakiety, venv, wersje, narzędzia, projekt)"]
R["ruff<br/>(linting + formatowanie)"]
TY["ty<br/>(kontrola typów - beta)"]
end
OLD ==>|konsolidacja| NEW
uv - kompleksowe zarządzanie projektem¶
Tip
uv to domyślna rekomendacja dla nowych projektów w Pythonie (stan na maj 2026). Jedno binarium zastępuje cały dolny rząd klasycznego stosu: pip, virtualenv, pyenv, pipx, poetry, pip-tools oraz twine.
uv to pojedyncze, samodzielne binarium napisane w języku Rust. Jego cechy:
-
Wydajność - operacje na zależnościach wykonuje 10–100x szybciej niż
pip. -
Licencja MIT - w pełni otwarte oprogramowanie.
-
Brak vendor lock-in -
uvtrzyma się standardowego plikupyproject.toml(PEP 6215). Projekt zarządzany przezuvpozostaje w pełni kompatybilny zpipi innymi narzędziami zgodnymi ze standardami.
Instalacja¶
uv instaluje się samodzielnym instalatorem, a nie przez pip - w ten sposób uv jest niezależne od jakiejkolwiek konkretnej instalacji Pythona (potrafi nawet sam pobierać interpretery):
# Linux / macOS
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
Workflow projektowy¶
To główny, zalecany sposób pracy z uv - pełne zarządzanie projektem, a nie tylko instalacja pakietów:
uv init my-project # nowy projekt: tworzy pyproject.toml i strukturę (venv + uv.lock powstają leniwie przy pierwszym `uv sync`/`uv run`)
uv add fastapi pydantic # dodaj zależność: resolve + lock + install (~0,5 s)
uv add --dev pytest ruff # zależności deweloperskie
uv remove fastapi # usuń zależność
uv sync # zsynchronizuj venv z lockfile
uv sync --frozen # CI: dokładnie wg lockfile, reprodukowalne buildy
uv run pytest # uruchom w venv BEZ aktywacji (`source .venv/bin/activate` zbędne)
uv run hello.py # uruchom skrypt
uv python install 3.14 # zainstaluj wersję Pythona (zastępuje pyenv)
uv tool install ruff # globalne narzędzie (zastępuje pipx)
uv pip sync requirements.txt # tryb kompatybilny z pip (dla starszych projektów)
Zwróć uwagę na uv run - uv sam dba o to, by skrypt wykonał się w odpowiednim środowisku wirtualnym z aktualnymi zależnościami. Ręczna aktywacja venva (source .venv/bin/activate) staje się zbędna.
Cały cykl życia projektu sprowadza się do kilku komend, które powtarzasz w pętli:
flowchart LR
A["uv init"] -->|"tworzy pyproject.toml"| B["uv add - zależności"]
B -->|"resolve + uv.lock + .venv"| C["uv run - uruchom kod"]
C -->|"potrzebna kolejna zależność"| B
C -.->|"CI / inna maszyna"| D["uv sync --frozen"]
D -.-> C
Benchmark wydajności¶
Pomiar przy zimnym cache, dla projektu fastapi + pydantic + pandas wraz z ~30 zależnościami tranzytywnymi1:
| Operacja | uv | Poetry | pip |
|---|---|---|---|
| Rozwiązanie zależności | ~0,5 s | ~30 s | zmienne |
| Instalacja pakietów | ~1,2 s | ~45 s | ~30 s |
| Utworzenie lockfile | natychmiast | minuty | brak lockfile |
Note
Czasy w tabeli mają charakter orientacyjny – rzędy wielkości odpowiadają publikowanym pomiarom Astral2. Konkretne wyniki zależą od projektu, sieci i sprzętu.
PEP 723 - skrypty z zależnościami inline¶
To jedna z najbardziej przełomowych funkcji uv. PEP 723 pozwala zadeklarować zależności wewnątrz samego pliku skryptu, w specjalnym komentarzu. Polecenie uv run hello.py samo pobierze odpowiednią wersję Pythona, zbuduje tymczasowe środowisko wirtualne i zainstaluje zależności - bez tworzenia projektu i bez requirements.txt:
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "requests>=2.31",
# "rich>=13.0",
# ]
# ///
import requests
from rich import print
resp = requests.get("https://api.github.com/repos/astral-sh/ruff")
stars = resp.json()["stargazers_count"]
print(f"Ruff has {stars} stars!")
Pojedynczy plik .py staje się w pełni samowystarczalnym, reprodukowalnym narzędziem - idealnie nadaje się na skrypty pomocnicze, automatyzacje i przykłady do dokumentacji.
uv w Dockerze i CI¶
W obrazie kontenera uv można skopiować bezpośrednio z oficjalnego obrazu, bez instalatora. Tryb --frozen gwarantuje, że build użyje dokładnie wersji z lockfile:
FROM python:3.12-slim
COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev
COPY . .
CMD ["uv", "run", "python", "-m", "app"]
Tip
Jeśli prowadzisz istniejący projekt oparty o requirements.txt + pip, migracja na uv jest prosta: uv init + uv add --requirements requirements.txt. Więcej szczegółów w dokumentacji uv migration guide.
venv i pip - podstawy oraz wiedza legacy¶
venv to moduł dostarczany ze standardową biblioteką Pythona, a pip to wbudowany instalator pakietów. Warto je znać - to fundament, na którym budują wszystkie nowsze narzędzia, i wciąż spotkasz je w niezliczonych istniejących projektach.
Typowy, klasyczny cykl pracy:
-
Tworzenie środowiska (np. w folderze
.venv): -
Aktywacja środowiska:
-
Instalacja pakietów za pomocą
pip: -
Zapisywanie zależności do pliku
requirements.txt:
Warning
Współczesnym standardem konfiguracji projektu jest pyproject.toml (PEP 621) wraz z plikiem lock (uv.lock), który zamraża dokładny, reprodukowalny zestaw wersji. Para requirements.txt + pip freeze to działające, ale minimalistyczne i z dzisiejszej perspektywy legacy podejście: pip freeze zrzuca jednym płaskim spisem zarówno zależności bezpośrednie, jak i tranzytywne - bez ich rozróżnienia - przez co trudno odczytać, czego projekt naprawdę wymaga.
Migracja istniejącego projektu na uv jest prosta:
uv init # utwórz pyproject.toml w istniejącym projekcie
uv add --requirements requirements.txt # zaimportuj zależności z requirements.txt
Poetry - starsza, wciąż popularna alternatywa¶
Poetry to dojrzałe narzędzie, które przed nadejściem uv było najczęstszym wyborem do zarządzania projektem i budowania pakietów. Wprowadziło do ekosystemu plik pyproject.toml jako centrum konfiguracji oraz poetry.lock dla deterministycznych instalacji.
Note
Poetry to dziś starsza, ale wciąż popularna alternatywa. Dla nowych projektów rekomendujemy uv; Poetry pozostaje rozsądnym wyborem przede wszystkim wtedy, gdy projekt już go używa i nie ma powodu do migracji.
Typowy cykl pracy:
-
Tworzenie nowego projektu:
-
Dodawanie zależności - Poetry automatycznie zapisze je w
pyproject.toml: -
Instalacja zależności z
poetry.lock(jeśli istnieje) lubpyproject.toml: -
Uruchamianie skryptów w środowisku zarządzanym przez Poetry:
Warning
Od wersji Poetry 2.0 (styczeń 2025) komenda poetry shell została wydzielona do osobnego pluginu i nie jest już dostępna domyślnie. Zamiast niej używaj poetry run <komenda> albo aktywuj środowisko przez poetry env activate.
Linting, formatowanie i kontrola typów¶
Trzy różne kategorie narzędzi pilnują jakości kodu Pythona. Łatwo je pomylić, więc warto jasno rozdzielić ich role:
-
Linter (
flake8,pylint,ruff) - czyta kod, ale go nie uruchamia. Flaguje potencjalne bugi, martwy (nieosiągalny) kod, nieużywane importy i zmienne oraz niebezpieczne wzorce. -
Formatter (
black,ruff format) - przepisuje kod do jednego, kanonicznego stylu. Eliminuje dyskusje o stylu na code review: nie ma już „twojego" i „mojego" formatowania, jest jedno. -
Type checker (
mypy,pyright,ty) - łapie błędy typów przed wdrożeniem. Działa jak kompilator znany z C++/C#, tyle że opcjonalny - analizuje wskazówki typów (type hints) i zgłasza niezgodności.
Ruff - jedno narzędzie zamiast pięciu¶
Ruff (Astral, Rust) łączy w jednym narzędziu funkcje lintera i formattera. Jest pełnoprawnym zamiennikiem black (formatter) oraz isort (sortowanie importów), pokrywa też większość reguł flake8 i znaczną część reguł pylint oraz bandit. Warto jednak wiedzieć, że Ruff nie jest jeszcze w 100% kompletnym zamiennikiem całego pylint ani bandit - część ich reguł i wtyczek wciąż nie ma odpowiednika. Mimo to dla zdecydowanej większości projektów sam Ruff w zupełności wystarcza:
-
implementuje ponad 900 reguł odtworzonych z 50+ wtyczek klasycznego ekosystemu
flake83; -
jest 10–100x szybszy niż
pylint- przelicenie ~50 000 linii kodu zajmuje mu około 1 sekundy; -
całe codzienne API to dwie komendy:
ruff check . --fix # lint + automatyczna naprawa wykrytych problemów
ruff format . # formatowanie kodu
Dwie szkoły konfiguracji w pyproject.toml¶
Szkoła 1 - inkrementalna: jawnie wybierasz konkretne rodziny reguł. Bezpieczne podejście do wdrażania ruff w istniejącym projekcie:
# Szkoła 1 - inkrementalna, jawna lista reguł
[tool.ruff]
line-length = 88
target-version = "py312"
[tool.ruff.lint]
select = ["E", "F", "I", "N", "UP", "B", "C4", "SIM"]
ignore = ["E501"]
[tool.ruff.format]
quote-style = "double"
Szkoła 2 - „włącz wszystko": aktywujesz wszystkie reguły i wyłączasz tylko te, które ci przeszkadzają. Świetne dla nowych projektów i wymagających zespołów:
# Szkoła 2 - "włącz wszystko"
[tool.ruff]
line-length = 88
preview = true
[tool.ruff.lint]
select = ["ALL"]
ignore = ["D203", "D213", "COM812"]
Integracja z VS Code¶
Po zainstalowaniu rozszerzenia charliermarsh.ruff dodaj do .vscode/settings.json, aby kod był lintowany, naprawiany i formatowany przy każdym zapisie:
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "charliermarsh.ruff",
"editor.codeActionsOnSave": {
"source.fixAll.ruff": "explicit",
"source.organizeImports.ruff": "explicit"
}
}
Integracja z pre-commit¶
Hook pre-commit uruchamia ruff automatycznie przy każdym commicie, zanim kod trafi do repozytorium. Plik .pre-commit-config.yaml:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.6 # użyj najnowszego tagu - `pre-commit autoupdate` zaktualizuje automatycznie
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
Note
Konkretne wersje hooków (rev:) szybko się starzeją - podane numery to tylko przykład z momentu pisania. Po utworzeniu pliku uruchom pre-commit autoupdate, aby podciągnąć wszystkie hooki do najnowszych tagów, i powtarzaj to okresowo.
Type checkery¶
Wskazówki typów same z siebie niczego nie sprawdzają - potrzebny jest type checker:
-
mypy- dojrzały, de facto standard, najszerzej wspierany przez ekosystem. -
pyright- type checker Microsoftu, osiąga najwyższą zgodność z oficjalną specyfikacją systemu typów; napędza wsparcie Pythona w VS Code. -
ty- type checker od Astral, w Rust, 10–100x szybszy odmypyi Pyright. Status: wczesna wersja eksperymentalna (0.0.x, od grudnia 2025). Domyka toolchainuv+ruff+ty.
Note
Narzędzia black, flake8 oraz isort traktuj dziś jako legacy - wciąż działają i są obecne w wielu projektach, ale w nowych projektach ich rolę w całości przejmuje ruff.
Note
W marcu 2026 Astral dołączyło do OpenAI4 - twórcę uv, ruff i ty. Narzędzia pozostają otwartoźródłowe (licencja MIT) i oparte na standardach PEP, więc dla użytkownika nic się nie zmienia.
Drugorzędnym, ale istotnym powodem, dla którego szybkość toolingu ma dziś znaczenie, jest era asystentów kodu. Modele takie jak Claude, Codex czy Copilot potrafią same wywołać linter lub type checker, sparsować jego wynik i na tej podstawie skorygować kod. Przy linterze działającym 30 sekund taka pętla samokorekty jest niepraktyczna; przy ruff zwracającym wynik w ~100 ms - staje się naturalna. Więcej o agentowych pętlach pracy z kodem znajdziesz w rozdziale 06-generative-ai-and-rag.md.
Wersje Pythona, conda i pixi¶
Zarządzanie wersjami Pythona¶
pyenv- klasyczne narzędzie do instalowania i przełączania wielu wersji interpretera Pythona obok siebie. Wciąż działa, ale w nowoczesnym workflow jest w dużej mierze zastępowane przezuv python install, które robi to samo bez dodatkowej zależności.
conda i Anaconda¶
conda to menedżer pakietów i środowisk, który wciąż pozostaje istotny w data science i ML. Jego przewaga nad pip polega na tym, że potrafi instalować nie tylko pakiety Pythona, lecz także zależności spoza ekosystemu Pythona: biblioteki C, kompilatory czy sterowniki CUDA - co bywa kluczowe przy konfiguracji środowisk GPU.
Tip
Jeśli używasz condy, instaluj pakiety z darmowego, społecznościowego kanału conda-forge zamiast z domyślnego kanału defaults - ten ostatni objęty jest komercyjnymi warunkami licencyjnymi Anacondy, które mogą obowiązywać większe organizacje.
pixi¶
pixi (firmy prefix.dev) to nowoczesna alternatywa, która łączy najlepsze z obu światów: korzysta z pakietów conda-forge oraz z PyPI, oferuje szybkie rozwiązywanie zależności i plik lock. Dobry wybór dla projektów ML wymagających zarówno bibliotek systemowych, jak i czystych pakietów Pythona.
Info
Notebooki świetnie nadają się do eksploracji, ale nigdy nie commituj wyników komórek zawierających dane wrażliwe (tokeny, klucze API, dane osobowe). Pliki .ipynb to dokumenty JSON – wyniki komórek są w nich zapisane jako plain text.
Jupyter Notebooks - interaktywne programowanie¶
Note
Jupyter Notebook to jedna z najpopularniejszych form pracy z Pythonem, szczególnie w data science, badaniach i nauczaniu. To interaktywne środowisko, gdzie kod, jego wyniki, wizualizacje i tekst (w formacie Markdown) współistnieją w jednym dokumencie (.ipynb).
Notebooki pozwalają na wykonywanie kodu w małych, niezależnych fragmentach (komórkach), co jest idealne do eksploracji danych i prototypowania algorytmów.
# W notebooku każda komórka wykonuje się osobno
# Komórka 1: Import bibliotek
import pandas as pd
import matplotlib.pyplot as plt
# Komórka 2: Wczytanie i wyświetlenie danych
# Wynik (tabela) wyświetli się bezpośrednio pod komórką
data = pd.read_csv('sales.csv')
data.head()
# Komórka 3: Wygenerowanie i wyświetlenie wykresu
# Wykres pojawi się bezpośrednio pod komórką
plt.figure(figsize=(10, 6))
plt.plot(data['date'], data['revenue'])
plt.title('Przychody w czasie')
plt.show()
Tip
Dzięki uv możesz uruchomić JupyterLab bez globalnej instalacji czegokolwiek - uv zbuduje na żądanie tymczasowe środowisko z Jupyterem:
Główne środowiska notebookowe¶
-
Jupyter Notebook / JupyterLab: Klasyczne, uruchamiane lokalnie w przeglądarce.
-
Google Colab: Darmowe notebooki w chmurze z dostępem do GPU i TPU od Google.
-
VS Code: Doskonałe, wbudowane wsparcie dla plików
.ipynb, łączące zalety IDE i notebooka. -
Platformy chmurowe: Databricks, Kaggle, Deepnote oferują zaawansowane, zespołowe środowiska notebookowe.
Warning
Notebooki mogą prowadzić do problemów z reprodukowalnością kodu, ponieważ kolejność wykonywania komórek ma znaczenie. Dla kodu produkcyjnego, który ma być uruchamiany automatycznie, preferowaną formą są standardowe pliki .py.
Wersjonowanie notebooków w git¶
Pliki .ipynb to w istocie dokumenty JSON zawierające również wyniki wykonania (w tym binarne obrazy wykresów). To sprawia, że git diff na notebooku bywa nieczytelny, a repozytorium puchnie. Dwa narzędzia rozwiązują ten problem:
-
jupytext- synchronizuje notebook z czytelnym dla człowieka plikiem.py(lub Markdown), który dobrze nadaje się do code review i wersjonowania. -
nbstripout- hook czyszczący wyniki komórek przed commitem, dzięki czemu do repozytorium trafia wyłącznie kod.
Źródła i przypisy¶
-
Benchmarki wydajności mają charakter orientacyjny - rzędy wielkości odpowiadają publikowanym pomiarom Astral; konkretne czasy zależą od projektu, sieci i sprzętu. ↩
-
Porównanie wydajności uv vs pip vs Poetry – zob. oficjalny benchmark Astral: docs.astral.sh/uv/#performance. ↩
-
Pełna lista reguł Ruff: docs.astral.sh/ruff/rules. ↩
-
Komunikat o dołączeniu Astral do OpenAI (marzec 2026): astral.sh/blog/openai. ↩
-
PEP 621 – Storing project metadata in pyproject.toml. Zob. peps.python.org/pep-0621. ↩