.. _root_redirect_stdout: Переопределение стандартного вывода =================================== ``Argenta`` предоставляет гибкие механизмы для форматирования вывода, включая динамические разделительные линии. Это достигается за счёт перехвата стандартного потока вывода (``stdout``), что накладывает некоторые особенности. ----- Механизм перехвата ``stdout`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ По умолчанию ``Argenta`` перехватывает весь текст, выводимый в ``stdout`` внутри обработчика команды. Это необходимо для реализации **динамических разделителей**: система анализирует вывод, находит самую длинную строку и использует её для отрисовки верхней и нижней границ. Такой подход создаёт аккуратный интерфейс, где вывод команды «обёрнут» в рамку, подогнанную под его содержимое. Пример приложения с динамической разделительной линией: .. image:: https://i.ibb.co/ZptzLJ1n/2025-11-03-121308.png :alt: Пример приложения с динамической разделительной линией Как вы можете заметить разделительная линия ровно той же длины, что и самая длинная строка в выводе. То же приложение с статической линией: .. image:: https://i.ibb.co/YFGRY2c0/2025-11-03-121650.png :alt: Пример приложения с статической разделительной линией В этом примере разделительная линия имеет фиксированную длину (по умолчанию 25 символов). ----- Побочные эффекты перехвата ``stdout`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Главный побочный эффект этого механизма проявляется при использовании функций, которые одновременно ожидают ввод от пользователя и выводят приглашение в консоль. Классический пример — стандартная функция ``input()``. .. code-block:: python :linenos: # Внутри обработчика команды user_name = input("Введите ваше имя: ") print(f"Привет, {user_name}!") .. warning:: При включённом перехвате ``stdout`` текст-приглашение (например, ``"Введите ваше имя: "``) **не будет выведен в консоль немедленно**. Он попадёт в буфер, и пользователь увидит только мигающий курсор. Текст приглашения отобразится лишь после завершения работы обработчика вместе с остальным выводом. Это может сбить пользователя с толку. ----- Отключение перехвата ``stdout`` с помощью ``disable_redirect_stdout`` --------------------------------------------------------------------- Чтобы решить эту проблему, в конструкторе ``Router`` предусмотрен специальный аргумент: * **disable_redirect_stdout** (``bool``, по умолчанию ``False``) Если при создании роутера установить ``disable_redirect_stdout=True``, механизм перехвата ``stdout`` будет отключён для всех его обработчиков. .. literalinclude:: ../code_snippets/redirect_stdout/sample.py :language: python :linenos: В этом случае ``input()`` будет работать как обычно, и пользователь сразу увидит приглашение к вводу. ----- Типы разделительных линий -------------------------- ``Argenta`` поддерживает два типа разделителей, которые настраиваются при инициализации ``App``: 1. **DynamicDividingLine()** * Поведение по умолчанию. Длина линии динамически подстраивается под самый длинный текст в выводе. * Требует включённого перехвата ``stdout`` (``disable_redirect_stdout=False`` в роутере). 2. **StaticDividingLine(length: int = 25)** * Линия имеет фиксированную длину (по умолчанию 25 символов), которую можно задать через аргумент `length`. * Используется принудительно для роутеров с ``disable_redirect_stdout=True``, так как без перехвата вывода невозможно определить динамическую длину. Настройка разделительной линии в `App` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Вы можете глобально задать тип разделителя для всего приложения через аргумент ``dividing_line`` в конструкторе ``App``. .. literalinclude:: ../code_snippets/redirect_stdout/sample2.py :language: python :linenos: ----- Итоговое поведение ------------------ .. list-table:: :widths: 25 25 35 15 :header-rows: 1 * - ``disable_redirect_stdout`` на ``Router`` - Тип линии в ``App`` - Фактическое поведение - ``input()`` работает корректно? * - ``False`` (по умолчанию) - ``DynamicDividingLine`` - Динамическая линия, длина по содержимому - Нет * - ``False`` (по умолчанию) - ``StaticDividingLine`` - Статическая линия указанной длины - Нет * - ``True`` - ``DynamicDividingLine`` - **Принудительно статическая линия** (длина по умолч.) - Да * - ``True`` - ``StaticDividingLine`` - Статическая линия указанной длины - Да Таким образом, для интерактивных команд, требующих ввода от пользователя, отключайте перехват ``stdout`` на уровне роутера. Для всех остальных команд можно оставить поведение по умолчанию.