Ползём в сеньоры. Вопросы к собеседованию на сеньора Python.
5 subscribers
4 links
Подготовка какие вопросы могут задавать для сеньора по python и framework
Download Telegram
🚀 DOCKER: МНОГОЭТАПНАЯ СБОРКА И HEALTHCHECKS — ЛИФТ НА СЕНЬОРА!

Привет, будущий Senior! 🧠 Разберем две мощные концепции для эффективного, безопасного и управляемого продакшена.

🎯 МНОГОЭТАПНАЯ СБОРКА

Зачем? Чтобы финальный образ весил 50 МБ вместо 1.5 ГБ! 💪

Решение: Разделяем сборку и запуск на разные этапы (stages) в одном Dockerfile.

Пример для Python:
# Этап 1: Сборщик
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN python -m venv /opt/venv \
&& . /opt/venv/bin/activate \
&& pip install --no-cache-dir -r requirements.txt

# Этап 2: Финальный образ
FROM python:3.11-alpine
WORKDIR /app
COPY --from=builder /opt/venv /opt/venv
COPY . .
ENV PATH="/opt/venv/bin:$PATH"
CMD ["python", "app.py"]


🔥 HEALTHCHECKS

Healthcheck — встроенный механизм самодиагностики контейнера.

Зачем в Dockerfile?
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 CMD curl -f http://localhost:8080/health/ || exit 1

ВАЖНОЕ РАЗГРАНИЧЕНИЕ:

1. Для Docker / Docker Compose — HEALTHCHECK из Dockerfile работает.
2. Для KubernetesHEALTHCHECK ИГНОРИРУЕТСЯ! 🚨 Используются Probes:
livenessProbe: Проверяет, жив ли контейнер.
readinessProbe: Проверяет, готов ли принимать трафик.

💎 ИТОГ:
Multi-stage — must have для прода: меньше размер, выше безопасность.
Healthchecks — понимай контекст: Dockerfile для standalone, свои probes для K8s.

Сеньор выбирает правильный инструмент для задачи. 👁️‍🗨️

#Docker #DevOps #SeniorPython
🔥 ТЫ ДУМАЕШЬ, ЧТО ЗНАЕШЬ ТЕСТЫ? А ЧТО НАСЧЁТ ПАРАМЕТРИЗАЦИИ В PYTEST? 🔥

Представь: ты пишешь тест для функции, которая проверяет, является ли число чётным. Ты бы написал 10 отдельных тестов для чисел 2, 4, 6, 8... А если их 100? 1000? Руки отсохнут, код раздуется, а время улетит в трубу. 😱

Вот тут и приходит СУПЕРСИЛА PYTESTпараметризованные тесты! Это как волшебная палочка, которая превращает один скучный тест в мощную машину для проверки сотен сценариев. 🪄

ЧТО ЭТО ТАКОЕ?
Параметризация — это когда ты пишешь ОДИН тест, а pytest запускает его МНОГО РАЗ с разными входными данными и ожидаемыми результатами. Всё гениально и просто!

КАК ЭТО ВЫГЛЯДИТ В КОДЕ?
Вместо того чтобы писать:
def test_is_even_2():
assert is_even(2) == True

def test_is_even_3():
assert is_even(3) == False


Ты пишешь ОДИН раз:
import pytest

@pytest.mark.parametrize("input, expected", [
(2, True),
(3, False),
(100, True),
(101, False),
])
def test_is_even(input, expected):
assert is_even(input) == expected


И ВСЁ! 🚀 Один тест, а проверяет 4 случая. Добавил ещё пару кортежей в список — и уже 1000 проверок!

ПОЧЕМУ ЭТО ТАК КРУТО?
Меньше кода — меньше шансов ошибиться.
Читаемость — сразу видно, какие кейсы покрыты.
Расширяемость — добавить новый сценарий = дописать одну строчку.
Изоляция — каждый запуск — независимый тест. Если один упал, остальные работают.

А ЧТО НАСЧЁТ СЛОЖНЫХ СЛУЧАЕВ?
Можно передавать не только простые значения, но и целые объекты, словари, функции! Хочешь проверить API с разными токенами? Легко:
@pytest.mark.parametrize("user_data", [
{"name": "Alice", "age": 30},
{"name": "Bob", "age": 25},
])
def test_user_creation(user_data):
result = create_user(user_data)
assert result["name"] == user_data["name"]


СОВЕТ ОТ СЕНЬОРА:
Параметризация — это не просто фишка. Это ОБЯЗАТЕЛЬНЫЙ инструмент в арсенале Senior Python разработчика. На собеседовании тебя спросят: "Как ты обеспечиваешь покрытие тестами?" — и твой ответ должен начинаться с "Параметризованные тесты в pytest...".

ЗАПОМНИ:
@pytest.mark.parametrize — твой лучший друг.
• Один тест — много данных.
• Код становится чище, а ты — увереннее.

Готовься к собесу и помни: сеньор не тот, кто пишет много кода, а тот, кто пишет умный код. 💪

#pytest #параметризация #seniorpython
🔥 Middleware в Django: что это и как написать свой?

Представь, что каждый HTTP-запрос к твоему сайту — это посетитель, который проходит через ряд «пропускных пунктов». Каждый пункт может проверить его, изменить или даже развернуть обратно. Вот это и есть middleware (промежуточное ПО).

Как это работает?

Django обрабатывает запрос по цепочке middleware. Каждый middleware — это класс с методами, которые вызываются на разных этапах:

__init__ — вызывается один раз при старте сервера.
__call__ — вызывается на каждый запрос.
process_request — до того, как Django определит, какой view обработает запрос.
process_view — после определения view, но до его вызова.
process_response — после того, как view вернул ответ.
process_exception — если в view возникло исключение.
process_template_response — если view вернул шаблонный ответ.

Зачем это нужно?

• Аутентификация и авторизация.
• Логирование запросов.
• Сжатие ответов.
• Блокировка подозрительных IP.
• Добавление заголовков безопасности.
• Обработка CORS.

Как написать кастомный middleware?

Самый простой способ — создать класс с методом __call__. Вот пример, который логирует время выполнения каждого запроса:


import time

class TimingMiddleware:
def __init__(self, get_response):
self.get_response = get_response

def __call__(self, request):
start = time.time()
response = self.get_response(request)
end = time.time()
print(f'Request took {end - start:.2f} seconds')
return response


Как подключить?

В файле settings.py добавь путь к твоему классу в список MIDDLEWARE:


MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
...
'myapp.middleware.TimingMiddleware',
]


Важные нюансы для Senior:

1. Порядок имеет значение — middleware выполняются в том порядке, в котором они указаны в списке. Первый middleware обрабатывает запрос первым, а ответ — последним.
2. Не делай тяжелых операций — каждый middleware выполняется на каждый запрос. Если там будет запрос к базе или внешнему API, производительность упадет.
3. Используй готовые решения — не изобретай велосипед. Django поставляется с набором встроенных middleware (аутентификация, сессии, CSRF, GZip и т.д.).
4. Тестируй — middleware могут влиять на все запросы, поэтому их нужно тщательно тестировать.
5. Не злоупотребляй — чем больше middleware, тем медленнее обработка. Держи цепочку минимальной.

Когда писать свой middleware?

Когда тебе нужно выполнить какое-то действие на каждом запросе или ответе, и это не вписывается в существующие механизмы Django (декораторы, сигналы, контекстные процессоры).

Например:
• Блокировка запросов с определенными User-Agent.
• Добавление кастомных заголовков к ответу.
• Изменение request.user на основе кастомной логики.

Итог:

Middleware — мощный инструмент, который позволяет «вклиниться» в обработку запроса/ответа. Понимание его работы — обязательный навык для Senior Python разработчика. На собеседовании тебя могут попросить написать простой middleware или объяснить, как работает цепочка. Теперь ты готов!

#Django #Middleware #SeniorPython
ТЫ ДУМАЕШЬ, ЧТО ЗНАЕШЬ SOLID? А СЛАБО ОБЪЯСНИТЬ, ПОЧЕМУ ТВОЙ DJANGO-ПРОЕКТ РАЗВАЛИВАЕТСЯ, КОГДА ТЫ МЕНЯЕШЬ ОДНУ СТРОЧКУ В МОДЕЛИ? 😱

Скорее всего, ты нарушаешь Dependency Inversion Principle (DIP) — принцип инверсии зависимостей. И сегодня мы разберем его так, что на собеседовании ты будешь сыпать терминами и примерами, как сеньор с 10-летним стажем. Поехали!

СУТЬ ПРИНЦИПА ОДНОЙ ФРАЗОЙ

Это правило говорит: НЕ ЗАВИСИ ОТ КОНКРЕТИКИ, ЗАВИСИ ОТ АБСТРАКЦИИ. Твой высокоуровневый код (бизнес-логика) не должен знать, как именно работает низкоуровневый код (база данных, API). Они оба должны общаться через интерфейс (абстракцию).

ПОЧЕМУ ЭТО ВАЖНО?

Представь, что твой сервис отправки писем — это розетка. А конкретная реализация (SMTP, Slack, Telegram) — это вилка. Если ты в коде жёстко прописал «шлём через SMTP», то при смене провайдера тебе придётся переписывать всю бизнес-логику. А если ты воткнул переходник (интерфейс), то просто меняешь вилку — и всё работает. 🔌

КАК ЭТО ВЫГЛЯДИТ В DJANGO?

Самый частый анти-паттерн — когда ты в views.py или services.py напрямую дёргаешь модель и её методы. Вот так делать НЕЛЬЗЯ:


# ПЛОХО: жёсткая зависимость от модели
from .models import Order

def send_invoice(order_id):
order = Order.objects.get(id=order_id)
# ... логика, которая знает про поля модели


А теперь — правильный подход. Мы создаём абстракцию (интерфейс) для работы с заказами:


# ХОРОШО: зависим от абстракции
from abc import ABC, abstractmethod

class OrderRepository(ABC):
@abstractmethod
def get_by_id(self, order_id):
pass

class DjangoOrderRepository(OrderRepository):
def get_by_id(self, order_id):
from .models import Order
return Order.objects.get(id=order_id)


Теперь твоя бизнес-логика зависит от интерфейса OrderRepository, а не от конкретной модели. И если завтра ты перейдёшь с PostgreSQL на MongoDB или вообще на внешний API — ты просто создашь новую реализацию интерфейса, и всё продолжит работать! 🚀

КАК ПРИМЕНИТЬ ЭТО В РЕАЛЬНОМ DJANGO-ПРОЕКТЕ?

1. Выдели интерфейсы для работы с данными. Не таскай Model.objects.filter() по всему проекту. Создай репозитории или сервисы.

2. Используй внедрение зависимостей (DI). Передавай зависимости в конструктор или метод, а не создавай их внутри. В Django для этого часто используют django-injector или просто передают зависимости через аргументы функций.

3. Для сложной бизнес-логики — отдельный слой. Не пиши всё во views.py. Вынеси логику в services.py, который будет зависеть от абстракций.

ЧАСТАЯ ОШИБКА НА СОБЕСЕДОВАНИИ

Многие путают DIP с Dependency Injection (DI). Запомни: DIP — это принцип (ЧТО делать), а DI — это паттерн (КАК делать). DIP говорит «зависи от абстракций», а DI предлагает способ это реализовать — передавать зависимости извне.

ПОЧЕМУ ЭТО СПАСЁТ ТВОЙ ПРОЕКТ?

Тестируемость. Ты можешь подменить реальный репозиторий на фейковый (mock) в тестах, не трогая базу данных.
Гибкость. Смена технологий становится простой заменой одной реализации на другую.
Читаемость. Код становится чище, потому что бизнес-логика не засорена деталями работы с БД.

ИТОГ

DIP — это не просто абстрактная теория из книжек. Это реальный инструмент, который делает твой код на Django гибким, тестируемым и готовым к изменениям. Начни с малого — вынеси работу с моделями в репозитории, и ты почувствуешь разницу.

А теперь вопрос к тебе: сколько мест в твоём проекте напрямую обращаются к Model.objects? Если больше десяти — пора рефакторить! 🔥

#Python #Django #SOLID #DIP #Собеседование #SeniorPython