Python Prompts for AI-Assisted Debugging, Testing and FastAPI Deployment in 2026

10 промтов для Python-разработчика: как закрывать задачи быстрее, пока коллеги гуглят исключения

Каждый Python-разработчик знает это чувство: ты уже третий раз гуглишь TypeError: 'NoneType' object is not subscriptable, листаешь Stack Overflow 2014 года и понимаешь, что ответ устарел ещё до выхода Python 3.10. Пока ты читаешь чужой вопрос, LLM уже могла бы написать тебе рабочий код — если правильно сформулировать запрос.

Проблема в том, что большинство промтов в интернете выглядят как «напиши функцию для сортировки». Это бесполезно. Хороший промт для Python — это не «сделай мне код», а «вот контекст, вот ограничения, вот ожидаемое поведение, покажи решение и объясни edge cases». Разница — как между pip install и pip install --no-cache-dir -r requirements.txt.

Ниже — 10 промтов, которые я реально использую в работе: от генерации типизированных функций до отладки падающих pytest-тестов и деплоя FastAPI. Каждый с примером, пояснением и указанием, для какой задачи подходит. Всё проверено на Python 3.12+ и актуальных версиях библиотек на сентябрь 2026.

1. Генерация типизированной функции с docstring по стандарту Google

Когда нужно быстро написать утилиту, но лень вспоминать формат docstring и аннотации типов. Промт заставляет модель сразу выдать production-ready код, а не псевдокод.

Промт:

You are a senior Python developer. Write a function with full type hints (PEP 484/604) and a Google-style docstring.
Signature requirements:
- Function name: {name}
- Inputs: {describe inputs}
- Output: {describe output}
- Must raise {ExceptionType} when {condition}
Return ONLY the function code, no explanations. Use Python 3.12 syntax (X | None instead of Optional[X]).

Пример использования: нужна функция, которая парсит строку с датой и возвращает datetime, кидая ValueError на пустой строке.

from datetime import datetime

def parse_date(value: str, fmt: str = "%Y-%m-%d") -> datetime:
    """Parse a date string into a datetime object.

    Args:
        value: Date string to parse.
        fmt: strptime format string, defaults to ISO-like "%Y-%m-%d".

    Returns:
        Parsed datetime object.

    Raises:
        ValueError: If value is empty or does not match fmt.
    """
    if not value:
        raise ValueError("value must be a non-empty string")
    return datetime.strptime(value, fmt)

Подходит для junior-задач, но с явным указанием типов выдаёт код, который проходит mypy --strict без правок.

2. Рефакторинг «божественного класса» в dataclass

Классика легаси: класс на 400 строк с кучей полей и методов. Промт помогает разбить его на dataclass + отдельные функции, сохранив поведение.

Промт:

Refactor the following Python class into a @dataclass (frozen if no mutation needed) plus pure functions.
Preserve the public API: same method names and signatures.
Do not change behavior. Point out any hidden state you found.
Class code:
{paste code}

Пример: класс User с полями name, email, created_at и методами is_active(), display_name(). На выходе — @dataclass(frozen=True) class User и функция display_name(user: User) -> str. Модель отдельно сообщит, что is_active зависел от глобального CURRENT_DATE, — это и есть «hidden state», который ломает тесты.

3. Pandas: векторизация вместо apply

df.apply(..., axis=1) на 10 млн строк работает часами. Промт заставляет переписать логику на векторные операции pandas.

Промт:

Rewrite this pandas code to avoid .apply(axis=1) and python-level loops.
Use vectorized operations (np.where, .map, .str accessor, boolean masks).
Keep the same output DataFrame columns and dtypes.
Benchmark hint: assume the DataFrame has 10M rows.
Code:
{paste code}

Пример: было

df["category"] = df.apply(
    lambda r: "big" if r["amount"] > 1000 and r["country"] == "US" else "small",
    axis=1,
)

стало

import numpy as np
df["category"] = np.where(
    (df["amount"] > 1000) & (df["country"] == "US"), "big", "small"
)

Для справки: официальная документация pandas в разделе Enhancing performance прямо рекомендует избегать apply там, где есть векторизация.

4. SQLAlchemy 2.0: async-запрос с relationship

Если вы мигрируете с SQLAlchemy 1.4 на 2.0, синтаксис select() с AsyncSession легко перепутать. Промт генерирует корректный async-запрос с selectinload.

Промт:

Write an async SQLAlchemy 2.0 query using AsyncSession.
Models: User (id, name), Order (id, user_id, total), relationship User.orders.
Task: fetch users with their orders where order.total > {threshold}, avoid N+1.
Use selectinload. Show the model definitions and the query.

Пример результата:

from sqlalchemy import select
from sqlalchemy.orm import selectinload

stmt = (
    select(User)
    .options(selectinload(User.orders))
    .where(User.orders.any(Order.total > threshold))
)
result = await session.execute(stmt)
users = result.scalars().unique().all()

Обратите внимание на .unique() — без него selectinload с коллекциями кидает InvalidRequestError. Документация SQLAlchemy 2.0 описывает это в разделе ORM Querying Guide.

5. pytest: параметризация и фикстуры вместо копипасты

Когда тесты копипастятся под каждый кейс. Промт превращает их в @pytest.mark.parametrize с фикстурами.

Промт:

Refactor these pytest tests:
- Replace repeated test bodies with @pytest.mark.parametrize
- Extract shared setup into fixtures
- Add edge cases I might have missed (empty input, None, boundary values)
- Use pytest.raises for error paths
Tests:
{paste tests}

Пример: вместо трёх тестов test_parse_iso, test_parse_slash, test_parse_dot получаем:

import pytest

@pytest.mark.parametrize("value,expected", [
    ("2026-09-26", datetime(2026, 9, 26)),
    ("2026/09/26", datetime(2026, 9, 26)),
    ("26.09.2026", datetime(2026, 9, 26)),
])
def test_parse_date(value, expected):
    assert parse_date(value, fmt=guess_fmt(value)) == expected

@pytest.mark.parametrize("bad", ["", None, "not-a-date"])
def test_parse_date_raises(bad):
    with pytest.raises(ValueError):
        parse_date(bad)

Плюс модель сама подсветит, что None без аннотации str | None вызовет TypeError до ValueError, — это ровно тот edge case, который забывают.

6. Оптимизация медленного кода: профилирование и замена алгоритма

Промт не просто «ускорь», а заставляет сначала оценить сложность.

Промт:

Analyze this Python function for performance.
1. Estimate time complexity (Big-O) of current implementation.
2. Identify the bottleneck.
3. Propose a faster version with better complexity.
4. Show how to verify with cProfile / timeit.
Code:
{paste code}

Пример: функция поиска дубликатов через вложенные циклы O(n²) переписывается на set за O(n):

def find_duplicates(items: list[int]) -> list[int]:
    seen: set[int] = set()
    dupes: set[int] = set()
    for x in items:
        if x in seen:
            dupes.add(x)
        seen.add(x)
    return list(dupes)

Проверка через стандартный модуль timeit (python -m timeit -s "...") показывает разницу на порядки уже на массиве в 100k элементов.

7. Обработка исключений и логирование без «except: pass»

Промт, который вычищает антипаттерн except Exception: pass и добавляет структурное логирование.

Промт:

Rewrite exception handling in this code:
- Catch only specific exceptions (no bare except)
- Add structured logging via the logging module (logger = logging.getLogger(__name__))
- Include context (function name, args) in log records
- Re-raise with 'raise ... from e' to preserve traceback
Code:
{paste code}

Пример: было

try:
    data = json.loads(raw)
except:
    pass

стало

import logging
logger = logging.getLogger(__name__)

try:
    data = json.loads(raw)
except json.JSONDecodeError as e:
    logger.warning("invalid json payload", extra={"raw_len": len(raw)})
    raise ValueError("payload is not valid JSON") from e

Это соответствует рекомендациям из PEP 3134 о chained exceptions и официальному Logging HOWTO.

8. Парсинг данных: httpx + selectolax вместо requests + BeautifulSoup

Промт для быстрого парсера, который не падает на динамических страницах и корректно ставит User-Agent.

Промт:

Write a Python parser using httpx (async) and selectolax.
Target: extract {fields} from {url}.
Requirements:
- Set a realistic User-Agent and timeout
- Handle HTTP 429 with exponential backoff (tenacity)
- Parse with CSS selectors, return list[dict]
- Do not use Selenium unless JS rendering is required

Пример:

import asyncio, httpx
from selectolax.parser import HTMLParser

async def fetch_titles(url: str) -> list[dict]:
    headers = {"User-Agent": "Mozilla/5.0 (compatible; MyBot/1.0)"}
    async with httpx.AsyncClient(timeout=10.0, headers=headers) as client:
        r = await client.get(url)
        r.raise_for_status()
    tree = HTMLParser(r.text)
    return [{"title": n.text(strip=True)} for n in tree.css("h2.article-title")]

asyncio.run(fetch_titles("https://example.com/blog"))

Важно: перед парсингом проверяйте robots.txt и условия сайта — это не техническое, но обязательное требование.

9. FastAPI: эндпоинт с Pydantic v2 и обработкой ошибок

Промт для генерации эндпоинта по актуальному синтаксису Pydantic v2 (model_config, field_validator).

Промт:

Write a FastAPI endpoint using Pydantic v2.
- Request model: {fields} with validation (e.g. email format, positive int)
- Response model with computed field
- Custom exception handler returning RFC 7807 problem+json
- Async DB call stub
Do not use deprecated Pydantic v1 syntax (no @validator, no Config class).

Пример:

from pydantic import BaseModel, EmailStr, Field, computed_field

class UserIn(BaseModel):
    email: EmailStr
    age: int = Field(gt=0, lt=120)

    @computed_field
    @property
    def domain(self) -> str:
        return self.email.split("@")[1]

RFC 7807 (application/problem+json) — реальный стандарт, описан в IETF RFC 7807. Он задаёт поля type, title, status, detail, instance для машиночитаемых ошибок API.

10. Деплой FastAPI: Dockerfile + healthcheck без раздутого образа

Финальный промт — упаковка сервиса в контейнер с multi-stage build и non-root пользователем.

Промт:

Write a production Dockerfile for a FastAPI app.
- Multi-stage: builder installs deps with pip --no-cache-dir into a venv, runtime copies venv
- Base image: python:3.12-slim
- Create non-root user, switch to it
- Add HEALTHCHECK hitting /health
- CMD: uvicorn with --workers {n}
Also show the matching docker-compose.yml with postgres and healthcheck.

Пример (фрагмент):

FROM python:3.12-slim AS builder
WORKDIR /app
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

FROM python:3.12-slim
COPY --from=builder /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
RUN useradd -m appuser
USER appuser
COPY . /app
WORKDIR /app
HEALTHCHECK CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Бонус — 11-й промт для отладки трейсбеков. Когда ничего не помогает, вставляете полный трейсбек и промт: Here is a Python traceback. Explain the root cause in 3 sentences, then give a minimal reproducible fix. Do not suggest reinstalling packages unless the traceback shows an import error. — это экономит десятки минут на гуглении.

Что важно помнить

Промты работают, когда вы даёте контекст: версию Python, версии библиотек, ожидаемое поведение и ограничения. Модель не знает, что у вас SQLAlchemy 2.0, а не 1.4, если вы не напишете это явно. И всегда проверяйте сгенерированный код: LLM уверенно выдаёт pd.append (удалён в pandas 2.0) или @validator из Pydantic v1, потому что в обучающих данных их было много. Комбинация «хороший промт + запуск тестов + чтение официальной документации» закрывает задачу быстрее, чем час поиска по Stack Overflow.

Начните с двух-трёх промтов из списка на ближайшей задаче — например, рефакторинга тестов и векторизации pandas. Дальше вы быстро соберёте свой набор под конкретный стек, и гуглить исключения придётся заметно реже.

← All posts

Comments