uv — забудьте про pip: Молниеносный менеджер Python-пакетов на языке Rust

uv — это чрезвычайно быстрый менеджер пакетов и исполнитель Python-скриптов, написанный на языке Rust. Он разработан командой Astral (создатели Ruff). По сути, это замена для pip, pip-tools и virtualenv, объединенная в одном компактном бинарном файле.

uv — это именно то решение, которое позволяет использовать Python в стиле «бинарник, который просто работает», не превращая систему в свалку.

Для тех, кто привык к PHP-стеку: uv — это нечто среднее между composer и автономным PHP-бинарником, который сам умеет подтягивать нужные расширения «на лету» без изменения системного окружения. Однако стоит понимать разделение: если uv идеален для автономных скриптов и Telegram-ботов, то для запуска тяжелых веб-интерфейсов на Flask или Django требуются другие инструменты (Gunicorn, Supervisor и т.д.). Подробнее об архитектуре таких решений и выборе правильной площадки я писал в статье про хостинг для Python и настройку связки Gunicorn + Flask.

Зачем это нужно, особенно на VPS с установленной панелью управления хостингом:

  1. Нулевая стоимость владения: Не требует установки системных компиляторов (build-essential), python3-dev и прочего мусора, который раздувает VPS.
  2. Изоляция «из коробки»: Полностью игнорирует системный Python. Ты никогда не сломаешь панель управления хостингом или системные скрипты Linux, так как uv работает в собственном кеше.
  3. Скорость: В 10–100 раз быстрее pip. Установка зависимостей происходит почти мгновенно благодаря эффективному кешированию и параллельной загрузке.
  4. Запуск «одной строкой»: Позволяет запускать скрипт, автоматически скачивая зависимости во временное окружение, не требуя предварительного создания venv.
  5. Экономия ресурсов: Оптимально управляет памятью при установке, что критично для дешевых VPS с риском OOM (Out Of Memory).

Если ознакомиться с официальной документацией, то вы увидите, что установка сводится к загрузке одного бинарного файла. Для системного использования на сервере (чтобы Fastpanel видела путь) лучше ставить в /usr/local/bin:

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

Получим примерно такое сообщение:

downloading uv 0.10.0 x86_64-unknown-linux-gnu
no checksums to verify
installing to /root/.local/bin
  uv
  uvx
everything's installed!
 
To add $HOME/.local/bin to your PATH, either restart your shell or run:
 
    source $HOME/.local/bin/env (sh, bash, zsh)
    source $HOME/.local/bin/env.fish (fish)

Поскольку uv — это просто статично скомпилированный бинарник на Rust, мы его просто перенесем в нужное место:

mv /root/.local/bin/uv /usr/local/bin/
mv /root/.local/bin/uvx /usr/local/bin/

Для проверки, что операцонная система видит бинарник, запустите например вывод версии:

 uv --version
uv 0.10.0

Создай файл, например, script.py. Этот код максимально прост и использует современную асинхронную библиотеку.

import asyncio
import logging
import sys
from aiogram import Bot, Dispatcher, html
from aiogram.filters import CommandStart
from aiogram.types import Message
 
# Настройка логирования для Fastpanel
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
 
TOKEN = "ТВОЙ_ТОКЕН_ОТ_BOTFATHER"
dp = Dispatcher()
 
@dp.message(CommandStart())
async def command_start_handler(message: Message) -> None:
    """Обработка команды /start"""
    user_name = html.bold(message.from_user.full_name)
    await message.answer(f"Привет, {user_name}! Я бот на Ubuntu 24.04, запущенный через uv.")
 
@dp.message()
async def echo_handler(message: Message) -> None:
    """Эхо-бот: отвечает тем же текстом, что прислал пользователь"""
    try:
        # Отправляем копию сообщения обратно
        await message.send_copy(chat_id=message.chat.id)
    except TypeError:
        # Если прислали что-то, что нельзя просто скопировать (например, стикер)
        await message.answer("Я получил твое сообщение, но не могу его просто скопировать.")
 
async def main() -> None:
    bot = Bot(token=TOKEN)
    logging.info("Бот вышел в онлайн...")
    await dp.start_polling(bot)
 
if __name__ == "__main__":
    asyncio.run(main())

Для традиционного запуска создайте файл requirements.txt в корне проекта с содержимыми:

aiogram==3.17.0

Теперь самое важное: как запустить это «чисто» через интерфейс панели. Зайди в Fastpanel → Нажми кнопку Создать сайт и выбери шаблон systemd

После создания зайдите в настройки сайта и заполните поля как указано на скриншоте ниже:

Вы меняете только параметр Launch command, все остальные параметры я оставил по умолчанию.

/usr/local/bin/uv run --with-requirements requirements.txt tg-to-wp2.py

Результат: Fastpanel создаст системный юнит, который будет следить за ботом. uv создаст свой локальный кеш именно внутри папок проекта, а не полезет в /root. Если бот упадет — панель его поднимет. Если ты обновишь код — просто нажми «Перегрузить» в интерфейсе панели Services твоего проекта. При этом в твоей операционной системе не появится ни одного нового Python-пакета в apt или глобальном pip.

Во всех вариантах запуска никаких `pip install` делать не нужно!

Во всех случаях uv использует глобальный кеш. Это значит, что если вы запускаете 10 разных ботов на одном сервере, использующих aiogram, библиотека скачается только один раз, но каждый бот будет изолирован. Это колоссальная экономия дискового пространства на дешевых VPS.

Вариант А: Традиционный (requirements.txt), создай файл requirements.txt в корне проекта с содержимыми

aiogram==3.17.0

Тогда команда запуска в Fastpanel изменится на:

/usr/local/bin/uv run --with-requirements requirements.txt script.py

Вариант Б: Экспертный (Inline Script Metadata — PEP 723). Это самый чистый способ для философии «минимум файлов». Ты прописываешь зависимости прямо внутри .py файла. uv их прочитает и сам все подготовит. В этом случае в папке вообще не будет лишних файлов, кроме самого скрипта.

# /// script
# dependencies = [
#   "aiogram",
# ]
# ///
 
import asyncio
import logging
import sys
 
# Остальной твой код

Тогда команда запуска

/usr/local/bin/uv run script.py

Вариант С: Самый простой. Здесь `–with aiogram` говорит `uv` автоматически подтянуть библиотеку во временное изолированное хранилище перед запуском. Если тебе понадобятся другие библиотеки (например, для работы с БД или WP API), просто добавь их через –with библиотека_имя прямо в эту строку.

/usr/local/bin/uv run --with aiogram --with aiohttp tg-to-wp.py

uv идеально подходит для запуска сервисных скриптов через CRON, так как тебе не нужно активировать виртуальные окружения или беспокоиться о путях к библиотекам.

Пример: Скрипт проверки срока жизни SSL-сертификата Этот скрипт проверяет, сколько дней осталось до истечения SSL любого домена.

Создай файл check_ssl.py:

# /// script
# dependencies = [
#   "cryptography",
# ]
# ///
 
import socket
import ssl
from datetime import datetime
from cryptography import x509
import sys
 
def get_ssl_expiry_date(hostname):
    context = ssl.create_default_context()
    with socket.create_connection((hostname, 443)) as sock:
        with context.wrap_socket(sock, server_hostname=hostname) as ssock:
            cert_bin = ssock.getpeercert(binary_form=True)
            cert = x509.load_der_x509_certificate(cert_bin)
            return cert.not_valid_after_utc
 
if len(sys.argv) < 2:
    print("Использование: uv run check_ssl.py domain.com")
    sys.exit(1)
 
domain = sys.argv[1]
expiry = get_ssl_expiry_date(domain)
days_left = (expiry - datetime.now(expiry.tzinfo)).days
 
print(f"Домен: {domain}")
print(f"Сертификат истекает: {expiry}")
print(f"Осталось дней: {days_left}")

Как это запускать? Просто из консоли (без установки чего-либо в систему):

/usr/local/bin/uv run check_ssl.py wiki.dieg.info

Получим примерно такой результат

Домен: wiki.dieg.info
Сертификат истекает: 2026-03-22 03:16:41+00:00
Осталось дней: 40

uv сам скачает библиотеку cryptography в свой временный кеш, выполнит скрипт и выдаст результат.

Почему это удобно?

  • Никакой подготовки: Тебе не нужно делать pip install cryptography или apt install python3-cryptography.
  • Чистый выхлоп: Ты получаешь только результат работы скрипта.
  • Переносимость: Ты можешь закинуть этот скрипт на любой свой VPS, где есть бинарник uv, и он сработает идентично.

Использование uv в связке с Fastpanel — это прагматичный выбор для тех, кто ценит стабильность PHP-стека, но нуждается в современных Python-инструментах. Мы получили архитектуру, где каждый скрипт живет в своем «пузыре», не конфликтует с системными пакетами и управляется через привычный GUI панели. Это полностью исключает риск падения панели управления из-за обновления библиотек и сводит администрирование к принципу «настроил и забыл».

Важное уточнение: Для запуска простых скриптов и демонов (как наш бот) возможностей uv более чем достаточно. Если же вы планируете строить сложные веб-сервисы, изучите нюансы настройки Gunicorn и выбора хостинга под Python — там архитектура деплоя будет отличаться.

Если ты годами сидел на PHP и привык, что окружение должно быть предсказуемым, uv — это твой входной билет в мир Python без головной боли. Ты получаешь мощь современных библиотек, сохраняя при этом сервер в девственной чистоте.

Читайте также: 5 вариантов Запуска скрипта на Python в Linux в фоновом режиме

📌 Удобный подбор VPS по параметрам доступен на DIEGfinder.com - официальном инструменте проекта DIEG. Это часть единой экосистемы, созданной для того, чтобы помочь быстро найти подходящий VPS/VDS сервер для любых задач хостинга.

📌 Для тестирования скриптов, установщиков VPN и Python-ботов рекомендуем использовать надежные VPS на короткий срок. Подробнее о быстрой аренде VPS для экспериментов - читайте здесь.

💥 Подпишись в Телеграм 💥 и задай вопрос по сайтам и хостингам бесплатно!