Files
Argenta/docs/root/redirect_stdout.rst
T
2025-11-02 00:17:28 +03:00

104 lines
6.2 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`` внутри обработчика команды. Это необходимо для реализации **динамических разделителей**: система анализирует вывод, находит самую длинную строку и использует её для отрисовки верхней и нижней границ. Такой подход создаёт аккуратный интерфейс, где вывод команды «обёрнут» в рамку, подогнанную под его содержимое.
-----
Побочные эффекты перехвата ``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`` на уровне роутера. Для всех остальных команд можно оставить поведение по умолчанию.