Files
Argenta/docs/root/redirect_stdout.rst
T

123 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`` внутри обработчика команды. Это необходимо для реализации **динамических разделителей**: система анализирует вывод, находит самую длинную строку и использует её для отрисовки верхней и нижней границ. Такой подход создаёт аккуратный интерфейс, где вывод команды «обёрнут» в рамку, подогнанную под его содержимое.
Пример приложения с динамической разделительной линией:
.. image:: https://i.ibb.co/yn9rWnNC/2025-11-07-180751.png
:alt: Example of an application with a dynamic dividing line
Как вы можете заметить, разделительная линия ровно той же длины, что и самая длинная строка в выводе.
То же приложение с статической линией:
.. image:: https://i.ibb.co/P8B4xyp/2025-11-07-180330.png
:alt: Example of an application with a static dividing line
В этом примере разделительная линия имеет фиксированную длину (по умолчанию 25 символов).
-----
Побочные эффекты перехвата ``stdout``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Побочный эффект этого механизма проявляется при использовании функций, которые последовательно выводят текст в консоль и ожидают ввод от пользователя. Классический пример — стандартная функция ``input()``.
.. code-block:: python
:linenos:
user_name = input("Enter your name: ")
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`` на уровне роутера. Для всех остальных команд можно оставить поведение по умолчанию.