Переопределение стандартного вывода¶
Argenta предоставляет гибкие механизмы для форматирования вывода, включая динамические разделительные линии. Это достигается за счёт перехвата стандартного потока вывода (stdout), что накладывает некоторые особенности.
Когда нужно отключать перехват stdout¶
Отключайте перехват stdout (disable_redirect_stdout=True в Router), если ваши команды:
✓ Используют input() для интерактивного ввода данных от пользователя
✓ Используют прогресс-бары (tqdm, rich.progress)
✓ Выводят данные в реальном времени (streaming, логи)
✓ Используют библиотеки, которые напрямую работают с stdout
Для обычных команд с print() перехват можно оставить включённым — это не влияет на их работу.
Механизм перехвата stdout¶
По умолчанию Argenta перехватывает весь текст, выводимый в stdout внутри обработчика команды. Это необходимо для реализации динамических разделителей: система анализирует вывод, находит самую длинную строку и использует её для отрисовки верхней и нижней границ. Такой подход создаёт аккуратный интерфейс, где вывод команды «обёрнут» в рамку, подогнанную под его содержимое.
Пример приложения с динамической разделительной линией:
Как вы можете заметить, разделительная линия ровно той же длины, что и самая длинная строка в выводе.
То же приложение с статической линией:
В этом примере разделительная линия имеет фиксированную длину (по умолчанию 25 символов).
Побочные эффекты перехвата stdout¶
Побочный эффект этого механизма проявляется при использовании функций, которые последовательно выводят текст в консоль и ожидают ввод от пользователя. Классический пример — стандартная функция input().
1user_name = input("Enter your name: ")
2print(f"Привет, {user_name}!")
Предупреждение
При включённом перехвате stdout текст (например, "Введите ваше имя: ") не будет выведен в консоль немедленно. Он попадёт в буфер и отобразится лишь после завершения работы обработчика вместе с остальным выводом. Это может сбить пользователя с толку.
Отключение перехвата stdout с помощью disable_redirect_stdout¶
Чтобы решить эту проблему, в конструкторе Router предусмотрен специальный аргумент:
disable_redirect_stdout (
bool, по умолчаниюFalse)
Если при создании роутера установить disable_redirect_stdout=True, механизм перехвата stdout будет отключён для всех его обработчиков.
Пример использования:
1from argenta import Response, Router
2
3# For this router stdout redirect will be disabled
4interactive_router = Router(disable_redirect_stdout=True)
5
6
7@interactive_router.command("ask")
8def ask_name(response: Response):
9 name = input("What is your name? ")
10 print(f"Nice to meet you, {name}!")
В этом случае input() будет работать как обычно, и пользователь сразу увидит приглашение к вводу.
Типы разделительных линий¶
Argenta поддерживает два типа разделителей, которые настраиваются при инициализации App:
- ``DynamicDividingLine()``
Поведение по умолчанию. Длина линии динамически подстраивается под самый длинный текст в выводе.
Требует включённого перехвата
stdout(disable_redirect_stdout=Falseв роутере).
- ``StaticDividingLine(length: int = 25)``
Линия имеет фиксированную длину (по умолчанию 25 символов), которую можно задать через аргумент
length.Используется принудительно для роутеров с
disable_redirect_stdout=True, так как без перехвата вывода невозможно определить динамическую длину.
Настройка разделительной линии в App¶
Вы можете глобально задать тип разделителя для всего приложения через аргумент dividing_line в конструкторе App.
Пример использования:
1from argenta import App
2from argenta.app import StaticDividingLine
3
4# All routers will use static line with length 50 by default
5app = App(dividing_line=StaticDividingLine(length=50))
Итоговое поведение¶
|
Тип линии в |
Фактическое поведение |
|
|---|---|---|---|
|
|
Динамическая линия, длина по содержимому |
Нет |
|
|
Статическая линия указанной длины |
Нет |
|
|
Принудительно статическая линия (длина по умолч.) |
Да |
|
|
Статическая линия указанной длины |
Да |
Таким образом, для интерактивных команд, требующих ввода от пользователя, отключайте перехват stdout на уровне роутера. Для всех остальных команд можно оставить поведение по умолчанию.