pip install, requirements.txt, virtualenv, black, isort, flake8, mypy, setup.py... Если вы настраиваете Python-проект так же, как в 2020 году, эта статья для вас. Показываю современный стек, который заменяет всё вышеперечисленное.

В 2026 году экосистема Python-инструментов наконец собралась в нечто цельное. Два инструмента (uv и ruff) + один файл (pyproject.toml) заменяют 7+ отдельных утилит. Вот как это работает.

Что заменяем и на что

Было

Стало

pip + pip-tools

uv

virtualenv / venv

uv

pyenv

uv

poetry / pipenv

uv

black (форматирование)

ruff format

isort (сортировка импортов)

ruff

flake8 (линтинг)

ruff check

setup.py / setup.cfg

pyproject.toml

requirements.txt

pyproject.toml + uv.lock

Два инструмента вместо девяти. Оба написаны на Rust, оба от Astral. Работают в 10-100 раз быстрее аналогов на Python.

Шаг 1. Установка uv

Одна команда:

# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windows
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

# Или через pip (если хочется по-старому)
pip install uv

Проверяем:

$ uv --version
uv 0.7.x

ruff ставить отдельно не нужно. uv умеет запускать его через uvx ruff. Но если хотите глобально:

uv tool install ruff

Шаг 2. Создаём проект

$ uv init myproject
Initialized project `myproject` at `./myproject`

$ cd myproject
$ ls
pyproject.toml  src/  README.md  .python-version

uv создал структуру проекта с pyproject.toml, папку src/ и файл .python-version. Никаких setup.pyrequirements.txtMakefile.

Если нужен Python конкретной версии:

# uv сам скачает и установит нужную версию Python
uv python install 3.13
uv python pin 3.13

Да, uv заменяет pyenv. Он сам управляет версиями Python.

Шаг 3. Зависимости

Забудьте pip install. Теперь так:

# Добавить зависимость
uv add requests
uv add pandas numpy

# Добавить dev-зависимость
uv add --dev pytest ruff

# Удалить зависимость
uv remove pandas

uv автоматически:

1. Создаёт виртуальное окружение (если его нет).
2. Добавляет пакет в pyproject.toml.
3. Обновляет lock-файл uv.lock.
4. Устанавливает пакет.

Всё за одну команду. Никаких pip freeze > requirements.txt.

Скорость

uv устанавливает пакеты в 10-100 раз быстрее pip. Холодная установка numpy + pandas + requests:

Инструмент

Время

pip

~12 сек

poetry

~8 сек

uv

~0.5 сек

Это не опечатка. uv кэширует пакеты глобально и использует жёсткие ссылки вместо копирования файлов.

Шаг 4. pyproject.toml

Вот как выглядит типичный pyproject.toml после настройки:

[project]
name = "myproject"
version = "0.1.0"
description = "My awesome project"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
    "requests>=2.32",
    "numpy>=2.0",
]

[dependency-groups]
dev = [
    "pytest>=8.0",
    "ruff>=0.9",
]

[tool.ruff]
target-version = "py312"
line-length = 88

[tool.ruff.lint]
select = [
    "E",    # pycodestyle errors
    "W",    # pycodestyle warnings
    "F",    # pyflakes
    "I",    # isort
    "UP",   # pyupgrade
    "B",    # flake8-bugbear
    "SIM",  # flake8-simplify
]

[tool.ruff.format]
quote-style = "double"

[tool.pytest.ini_options]
testpaths = ["tests"]

Один файл. Зависимости, линтер, форматтер, тесты. Всё здесь.

Шаг 5. Линтинг и форматирование (ruff)

ruff заменяет flake8 + black + isort + pyupgrade. Одна команда вместо четырёх.

# Проверить код
uvx ruff check .

# Проверить и автоматически исправить
uvx ruff check --fix .

# Отформатировать код (замена black)
uvx ruff format .

# Проверить форматирование без изменений
uvx ruff format --check .

Скорость ruff

ruff проверяет код в 10-100 раз быстрее flake8. На проекте из 1000 файлов:

Инструмент

Время

flake8

~12 сек

flake8 + isort + black

~25 сек

ruff check + ruff format

~0.3 сек

Пример: что ruff ловит

# До
import os
import sys
from typing import Optional, List, Dict
import json

def process(data: Optional[List[Dict[str, str]]] = None):
    if data == None:
        data = list()
    for item in data:
        if len(item.keys()) > 0:
            print(item)
# После ruff check --fix + ruff format
import json

def process(data: list[dict[str, str]] | None = None):
    if data is None:
        data = []
    for item in data:
        if item:
            print(item)

Что ruff сделал:

1. Убрал неиспользуемые импорты (ossys).
2. Отсортировал оставшиеся импорты.
3. Заменил Optional[List[Dict]] на list[dict] | None (Python 3.10+).
4. Заменил == None на is None.
5. Заменил list() на [].
6. Упростил len(item.keys()) > 0 до item.

Шаг 6. Запуск скриптов

Для запуска скриптов внутри виртуального окружения:

# Запуск скрипта
uv run python src/myproject/main.py

# Запуск тестов
uv run pytest

# Запуск любой команды в окружении
uv run mycommand

uv run автоматически активирует виртуальное окружение. Не нужно никаких source .venv/bin/activate.

Одноразовые скрипты

Нужно быстро запустить скрипт с зависимостями, не создавая проект?

# Запустить скрипт, который требует requests, без установки
uv run --with requests python script.py

# Запустить инструмент одноразово (npx-стиль)
uvx black .
uvx httpie https://api.github.com

uvx = npx для Python. Скачивает, запускает, не засоряет систему.

Шаг 7. CI/CD

Минимальный GitHub Actions workflow:

# .github/workflows/ci.yml
name: CI
on: [push, pull_request]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v5

      - run: uv sync
      - run: uvx ruff check .
      - run: uvx ruff format --check .
      - run: uv run pytest

4 строки. Установка зависимостей, линтинг, форматирование, тесты. Всё.

Время CI на типичном проекте:

Стек

Время

pip + flake8 + black + pytest

~45 сек

poetry + flake8 + black + pytest

~60 сек

uv + ruff + pytest

~12 сек

Шаг 8. Docker

Минимальный Dockerfile:

FROM python:3.13-slim

# Установить uv
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv

# Копировать файлы проекта
WORKDIR /app
COPY pyproject.toml uv.lock ./

# Установить зависимости (кэшируется Docker layer)
RUN uv sync --no-dev --frozen

# Копировать код
COPY src/ src/

CMD ["uv", "run", "python", "-m", "myproject"]

Важный момент: pyproject.toml и uv.lock копируются отдельно от кода. Это позволяет Docker кэшировать слой с зависимостями. Если код изменился, а зависимости нет, переустановки не будет.

Миграция с pip/poetry за 2 минуты

С requirements.txt

# Инициализировать проект
uv init

# Импортировать зависимости из requirements.txt
uv add $(cat requirements.txt)

С poetry

uv понимает pyproject.toml в формате Poetry. Просто:

# Удалить poetry.lock, создать uv.lock
rm poetry.lock
uv lock
uv sync

Если в pyproject.toml есть секция [tool.poetry], uv прочитает зависимости оттуда.

Полный чеклист нового проекта

# 1. Создать проект
uv init myproject && cd myproject

# 2. Добавить зависимости
uv add requests pydantic

# 3. Добавить dev-зависимости
uv add --dev pytest ruff

# 4. Написать код
# ...

# 5. Проверить и отформатировать
uvx ruff check --fix .
uvx ruff format .

# 6. Запустить тесты
uv run pytest

# 7. Готово

Пять минут. Никаких setup.pyMANIFEST.inrequirements.txttox.ini.flake8.isort.cfgpyproject.toml на 200 строк.

uv + ruff + pyproject.toml = всё, что нужно для Python-проекта в 2026 году.

Ссылки

uv на GitHub (80k+ звёзд)
ruff на GitHub (40k+ звёзд)
Документация uv
Документация ruff
PEP 621: стандарт pyproject.toml

Комментарии (6)


  1. rSedoy
    07.06.2026 11:52

    Python-проект в 2026

    вот не люблю такие заявления, всё описанное тут было актуальным и в 2025 году, да и uv 0.7.x намекает на прошлый год.


  1. robert_ayrapetyan
    07.06.2026 11:52

    Что насчет веб фреймворка? Что сейчас носят?


  1. avasiukevich
    07.06.2026 11:52

    Хороший гайд!

    Недавно пришлось с нуля создавать новый проект на питоне (впервые за много лет), почти все также в итоге настроил

    Я бы еще добавил в базовую конфигурацию проекта:

    1. скрипт первичной настройки для новых разработчиков (сильно упрощает онбординг)

    2. настройку типичных команд и сценариев в just / make (так как uv это все же не lifecycle manager)

    3. проверку типизации (mypy)

    4. набор pre-commit хуков (проверить форматирование, консистентность окружения, мелкие типичные проблемы, и т д)


  1. ceveru
    07.06.2026 11:52

    А Хаб Java - это по тому что у автора рука дрогнула?


  1. orki
    07.06.2026 11:52

    Пять минут. Никаких setup.pyMANIFEST.inrequirements.txttox.ini.flake8.isort.cfgpyproject.toml на 200 строк.

    про pyproject.toml - наглая ложь не соответствует реалиям. Все настройки ruff, pytest, mypy или pyright - все будет в нём, если у вас не одноразовый проект (но тогда и ci cd вам не нужен как таковой)

    Но в целом ок, помимо тестов и проверки типов через mypy или pyright, я бы добавил еше проверку пакетов на уязвимости через uv audit


  1. ophil
    07.06.2026 11:52

    если уж тул на раст, то установка `cargo -v install uv`, можно заодно и `cargo -v install just`