Найти в Дзене
AI_ML

Модульная разработка Streamlit-приложений: от правильной структуры до промпта для LLM 🚀

При создании даже небольшого приложения для анализа данных, код имеет тенденцию быстро разрастаться. Вся логика, смешанная в одном файле app.py — загрузка данных, их обработка, построение графиков, элементы интерфейса — превращается в так называемый "код-спагетти". Его сложно читать, невозможно тестировать и практически нереально поддерживать или расширять. Решение этой проблемы — модульная разработка. Это подход, при котором приложение разбивается на небольшие, независимые и взаимозаменяемые части (модули), каждая из которых отвечает за одну конкретную задачу. Хорошая структура — это фундамент вашего приложения. Для Streamlit-приложения по анализу данных идеально подходит следующая структура: Объяснение каждого элемента: Давайте создадим простое приложение, которое загружает CSV-файл, показывает основную статистику и строит гистограмму для выбранного столбца. src/data_processing.py (Отвечает только за анализ) src/plotting.py (Отвечает только за графики) main.py (Собирает все вместе в
Оглавление

При создании даже небольшого приложения для анализа данных, код имеет тенденцию быстро разрастаться. Вся логика, смешанная в одном файле app.py — загрузка данных, их обработка, построение графиков, элементы интерфейса — превращается в так называемый "код-спагетти". Его сложно читать, невозможно тестировать и практически нереально поддерживать или расширять.

Решение этой проблемы — модульная разработка. Это подход, при котором приложение разбивается на небольшие, независимые и взаимозаменяемые части (модули), каждая из которых отвечает за одну конкретную задачу.

## Почему модульность — это ключ к успеху? 🧠

  1. Читаемость и поддержка (Readability & Maintainability): Вместо одного файла на 1000 строк у вас будет несколько файлов по 50-100 строк. Найти нужный фрагмент кода, отвечающий за построение графика, становится тривиальной задачей — вы просто открываете plotting.py.
  2. Повторное использование кода (Reusability): Функцию загрузки данных из модуля data_loader.py можно использовать на разных страницах вашего Streamlit-приложения или даже в других проектах.
  3. Упрощение тестирования (Testability): Вы можете написать тесты для конкретной функции (например, для очистки данных) в полной изоляции от пользовательского интерфейса Streamlit. Это делает тесты надежнее и проще.
  4. Параллельная разработка (Teamwork): Один разработчик может работать над модулем визуализации, а другой — над модулем загрузки данных, не мешая друг другу.

## Правильная организация структуры проекта 📂

Хорошая структура — это фундамент вашего приложения. Для Streamlit-приложения по анализу данных идеально подходит следующая структура:

-2

Объяснение каждого элемента:

  • main.py: Это ваша точка входа. Этот файл должен быть "тонким". Его задача — импортировать функции из модулей в src/ и собрать из них пользовательский интерфейс с помощью команд st.title, st.button, st.dataframe и т.д. Он не должен содержать сложной логики обработки данных.
  • src/: Здесь живет вся бизнес-логика.
    data_loader.py: Содержит функции для загрузки данных из разных источников (CSV, Excel, API, база данных).
    data_processing.py: Функции для очистки данных, создания новых признаков, фильтрации.
    plotting.py: Функции, которые принимают на вход DataFrame и возвращают готовый график (например, объект Plotly или Matplotlib).
  • pages/: Встроенная функция Streamlit. Любой .py файл в этой директории автоматически становится отдельной страницей в вашем приложении.
  • requirements.txt: Список всех библиотек, необходимых для работы проекта (streamlit, pandas, plotly и т.д.).

## Пример: Модульное приложение для анализа данных 📊

Давайте создадим простое приложение, которое загружает CSV-файл, показывает основную статистику и строит гистограмму для выбранного столбца.

requirements.txt

-3

src/data_processing.py (Отвечает только за анализ)

-4

src/plotting.py (Отвечает только за графики)

столбца "{column_name}"')
столбца "{column_name}"')

main.py (Собирает все вместе в интерфейс)

-6

Как видите, main.py не выполняет никакой "грязной" работы. Он действует как дирижер, вызывая нужные функции из оркестра модулей в src/.

## Промпт для LLM (ChatGPT, Gemini и др.)

Чтобы заставить языковую модель сгенерировать код в таком стиле, нужен очень точный и структурированный промпт. Вот пример такого промпта.

**Роль:** Ты — опытный Python-разработчик, специализирующийся на создании поддерживаемых и масштабируемых веб-приложений для анализа данных с использованием Streamlit. Твой главный приоритет — чистота кода, следование принципу единственной ответственности (Single Responsibility Principle) и строгая модульная архитектура.
**Задача:** Создай код для простого Streamlit-приложения, которое выполняет следующие функции:
1. Загружает CSV-файл, предоставленный пользователем.
2. Выводит первые 10 строк загруженного датафрейма.
3. Позволяет пользователю выбрать один из числовых столбцов.
4. Строит и отображает диаграмму рассеяния (scatter plot) для двух выбранных пользователем числовых столбцов.
**Технологический стек:**
- Python 3.9+
- Streamlit
- Pandas
- Plotly Express
**Строгие ограничения и требования к архитектуре:**
1. **Модульная структура:** Весь код должен быть разделен на модули внутри директории `src/`. Главный файл `main.py` должен содержать только UI-логику и вызывать функции из модулей.
2. **Структура файлов:** Ты должен предоставить код для следующих файлов:
- `main.py` (точка входа, UI)
- `src/data_loader.py` (только функции для загрузки данных)
- `src/plotting.py` (только функции для создания графиков)
- `src/utils.py` (вспомогательные функции, например, для получения списка числовых столбцов)
- `requirements.txt` (файл зависимостей)
3. **Ограничение по длине модуля:** **КРАЙНЕ ВАЖНО!** Каждый файл с кодом Python (`.py`) не должен превышать **70 строк кода** (не считая пустых строк и комментариев). Это заставит тебя придерживаться принципа единственной ответственности.
4. **Чистота функций:** Функции должны быть "чистыми" — принимать данные как аргументы и возвращать результат. Они не должны полагаться на глобальные переменные. Используй аннотации типов (type hints).
5. **Кэширование:** Используй декоратор `@st.cache_data` для функции загрузки данных для оптимизации производительности.
**Формат вывода:**
Предоставь ответ в виде последовательности блоков кода. Каждый блок должен начинаться с полного пути к файлу (например, `src/data_loader.py`), за которым следует сам код.
Начинай генерацию.

Этот промпт четко определяет роль, задачу, структуру, технологии и, что самое важное, жесткие ограничения, которые заставляют модель следовать модульному подходу, а не сваливать все в один файл. Указание на ограничение количества строк — это мощный трюк, заставляющий LLM дробить логику на более мелкие функции и файлы.