- PVSM.RU - https://www.pvsm.ru -
pip install, requirements.txt, virtualenv, black, isort, flake8, mypy, setup.py [1]... Если вы настраиваете Python-проект так же, как в 2020 году, эта статья для вас. Показываю современный стек, который заменяет всё вышеперечисленное.
В 2026 году экосистема Python-инструментов наконец собралась в нечто цельное. Два инструмента (uv [2] и ruff [3]) + один файл (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 [1] / setup.cfg |
pyproject.toml |
|
requirements.txt |
pyproject.toml + uv.lock |
Два инструмента вместо девяти. Оба написаны на Rust, оба от Astral [4]. Работают в 10-100 раз быстрее аналогов на Python.
Одна команда:
# 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
$ 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.py [1], requirements.txt, Makefile.
Если нужен Python конкретной версии:
# uv сам скачает и установит нужную версию Python
uv python install 3.13
uv python pin 3.13
Да, uv заменяет pyenv. Он сам управляет версиями Python.
Забудьте 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 кэширует пакеты глобально и использует жёсткие ссылки вместо копирования файлов.
Вот как выглядит типичный 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"]
Один файл. Зависимости, линтер, форматтер, тесты. Всё здесь.
ruff заменяет flake8 + black + isort + pyupgrade. Одна команда вместо четырёх.
# Проверить код
uvx ruff check .
# Проверить и автоматически исправить
uvx ruff check --fix .
# Отформатировать код (замена black)
uvx ruff format .
# Проверить форматирование без изменений
uvx ruff format --check .
ruff проверяет код в 10-100 раз быстрее flake8. На проекте из 1000 файлов:
|
Инструмент |
Время |
|---|---|
|
flake8 |
~12 сек |
|
flake8 + isort + black |
~25 сек |
|
ruff check + ruff format |
~0.3 сек |
# До
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. Убрал неиспользуемые импорты (os, sys).
2. Отсортировал оставшиеся импорты.
3. Заменил Optional[List[Dict]] на list[dict] | None (Python 3.10+).
4. Заменил == None на is None.
5. Заменил list() на [].
6. Упростил len(item.keys()) > 0 до item.
Для запуска скриптов внутри виртуального окружения:
# Запуск скрипта
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. Скачивает, запускает, не засоряет систему.
Минимальный 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 сек |
Минимальный 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 кэшировать слой с зависимостями. Если код изменился, а зависимости нет, переустановки не будет.
# Инициализировать проект
uv init
# Импортировать зависимости из requirements.txt
uv add $(cat requirements.txt)
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.py [1], MANIFEST.in [5], requirements.txt, tox.ini, .flake8, .isort.cfg, pyproject.toml на 200 строк.
uv + ruff + pyproject.toml = всё, что нужно для Python-проекта в 2026 году.
uv на GitHub [2] (80k+ звёзд)
ruff на GitHub [3] (40k+ звёзд)
Документация uv [6]
Документация ruff [7]
PEP 621 [8]: стандарт pyproject.toml
Автор: scandinavi
Источник [9]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/python/452820
Ссылки в тексте:
[1] setup.py: http://setup.py
[2] uv: https://github.com/astral-sh/uv
[3] ruff: https://github.com/astral-sh/ruff
[4] Astral: https://astral.sh/
[5] MANIFEST.in: http://MANIFEST.in
[6] Документация uv: https://docs.astral.sh/uv/
[7] Документация ruff: https://docs.astral.sh/ruff/
[8] PEP 621: https://peps.python.org/pep-0621/
[9] Источник: https://habr.com/ru/articles/1044550/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1044550
Нажмите здесь для печати.