.. _root_redirect_stdout: Переопределение стандартного вывода =================================== О разделе ~~~~~~~~~ ``Argenta`` предоставляет гибкие механизмы для управления форматированием вывода, включая использование динамических разделительных линий. Это достигается за счет перехвата стандартного потока вывода (``stdout``), что имеет свои особенности. ----- Механизм перехвата ``stdout`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ По умолчанию ``Argenta`` перехватывает весь текст, который выводится в ``stdout`` внутри обработчика команды (``handler``). Это делается для реализации **динамической длины разделителя**. Система анализирует весь выведенный текст, находит самую длинную строку и использует её длину для отрисовки верхней и нижней разделительных линий. Это создает аккуратный и визуально согласованный интерфейс, где вывод команды "обернут" в рамку, идеально подогнанную под его содержимое. ----- Побочные эффекты перехвата ``stdout`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Главный побочный эффект этого механизма проявляется при использовании функций, которые одновременно ожидают ввод от пользователя и выводят текст-приглашение. Классический пример — стандартная функция ``input()``. .. code-block:: python :linenos: # Внутри обработчика команды user_name = input("Введите ваше имя: ") print(f"Привет, {user_name}!") .. warning:: При включенном перехвате ``stdout`` текст-приглашение ``"Введите ваше имя: "`` **не будет выведен в консоль немедленно**. Он попадет в буфер, и пользователь увидит только мигающий курсор, ожидающий ввода. Текст приглашения будет выведен только после того, как выполнение всего обработчика завершится, вместе с остальным буферизованным выводом. Это может сбить пользователя с толку и является пограничным случаем, требующим внимания при разработке. ----- Отключение перехвата ``stdout`` с помощью ``disable_redirect_stdout`` --------------------------------------------------------------------- Чтобы решить проблему с ``input()`` и другими подобными функциями, в конструкторе класса ``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`` на соответствующем роутере. Для всех остальных команд можно оставить поведение по умолчанию.