Files
Argenta/docs/root/redirect_stdout.rst
T
2025-10-21 10:33:46 +03:00

107 lines
6.8 KiB
ReStructuredText
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
.. _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_example_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_example_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`` на соответствующем роутере. Для всех остальных команд можно оставить поведение по умолчанию.