🤔 Можно ли извлечь элемент генератора по индексу?
Нет, генераторы не поддерживают индексацию. Их элементы можно получить только путём итерации.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Нет, генераторы не поддерживают индексацию. Их элементы можно получить только путём итерации.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍1
🤔 Как понять, какие виды тестов нужны именно сейчас?
Выбор типа тестирования зависит от целей, стадии разработки и текущих проблем. Чтобы определить, какие тесты нужны, стоит ответить на вопросы:
Что тестируем? (код, API, UI, производительность и т. д.)
Какие риски? (где может сломаться, критичность ошибки)
Какой этап разработки? (новый код, рефакторинг, релиз)
🚩Как определить нужные тесты прямо сейчас?
🟠Только написали новый код
Нужны: Юнит-тесты
Тестируем функции и классы отдельно.
🟠Соединяем модули или работаем с API
Нужны: Интеграционные тесты
Проверяем работу всей системы вместе.
🟠Перед релизом или деплоем
Нужны: Функциональные и регрессионные тесты
Проверяем ключевые сценарии и старый функционал.
🟠Изменили UI (например, фронтенд на React)
Нужны: UI-тесты (Selenium, Playwright)
Проверяем нажатие кнопок, формы и отображение страниц.
🟠Если проект должен выдерживать большую нагрузку
Нужны: Нагрузочные тесты (Load Testing)
Используем
Ставь 👍 и забирай 📚 Базу знаний
Выбор типа тестирования зависит от целей, стадии разработки и текущих проблем. Чтобы определить, какие тесты нужны, стоит ответить на вопросы:
Что тестируем? (код, API, UI, производительность и т. д.)
Какие риски? (где может сломаться, критичность ошибки)
Какой этап разработки? (новый код, рефакторинг, релиз)
🚩Как определить нужные тесты прямо сейчас?
🟠Только написали новый код
Нужны: Юнит-тесты
Тестируем функции и классы отдельно.
def add(a, b):
return a + b
def test_add():
assert add(2, 3) == 5 # ✅ Юнит-тест
🟠Соединяем модули или работаем с API
Нужны: Интеграционные тесты
Проверяем работу всей системы вместе.
def test_api():
response = requests.get("https://api.example.com/data")
assert response.status_code == 200
🟠Перед релизом или деплоем
Нужны: Функциональные и регрессионные тесты
Проверяем ключевые сценарии и старый функционал.
def test_login():
assert login("user", "password") == "Success"
🟠Изменили UI (например, фронтенд на React)
Нужны: UI-тесты (Selenium, Playwright)
Проверяем нажатие кнопок, формы и отображение страниц.
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://example.com")
assert "Example" in driver.title
🟠Если проект должен выдерживать большую нагрузку
Нужны: Нагрузочные тесты (Load Testing)
Используем
locust, JMeter, k6, чтобы проверить сколько пользователей выдержит сервер. from locust import HttpUser, task
class MyUser(HttpUser):
@task
def test_homepage(self):
self.client.get("/")
Ставь 👍 и забирай 📚 Базу знаний
👍1
🤔 Объясни как происходит обработка HTTP запросов на Django
Когда пользователь отправляет HTTP-запрос (например, открывает страницу сайта), Django проходит несколько этапов обработки, прежде чем вернуть ответ.
🚩Подробный разбор обработки HTTP-запроса в Django
🟠Запрос приходит в WSGI/ASGI сервер
Когда клиент (браузер, API) отправляет запрос, его принимает WSGI/ASGI-сервер (
Если проект синхронный → работает через WSGI (
Если проект асинхронный → через ASGI (
🟠Django создаёт `HttpRequest` объект
Django превращает HTTP-запрос в объект
🟠Middleware (промежуточная обработка)
Прежде чем запрос дойдёт до
Проверять авторизацию (
Защищать от CSRF (
Перенаправлять запросы (
🟠Поиск `view` в `urls.py`
Django ищет, какая функция (
🟠Выполнение `view` (контроллера)
Когда Django находит подходящее представление (
🟠Формирование и обработка ответа
Django берёт
🟠WSGI/ASGI сервер отправляет ответ клиенту
На последнем этапе WSGI/ASGI-сервер отправляет ответ обратно браузеру или API-клиенту.
🚩Краткая схема обработки запроса
Ставь 👍 и забирай 📚 Базу знаний
Когда пользователь отправляет HTTP-запрос (например, открывает страницу сайта), Django проходит несколько этапов обработки, прежде чем вернуть ответ.
🚩Подробный разбор обработки HTTP-запроса в Django
🟠Запрос приходит в WSGI/ASGI сервер
Когда клиент (браузер, API) отправляет запрос, его принимает WSGI/ASGI-сервер (
Gunicorn, Daphne). Если проект синхронный → работает через WSGI (
wsgi.py). Если проект асинхронный → через ASGI (
asgi.py). GET /hello/ HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
🟠Django создаёт `HttpRequest` объект
Django превращает HTTP-запрос в объект
HttpRequest, который передаётся в view. def my_view(request):
print(request.method) # 'GET'
print(request.path) # '/hello/'
print(request.GET) # {'name': 'Alice'}
🟠Middleware (промежуточная обработка)
Прежде чем запрос дойдёт до
view, Django проходит через мидлвари, которые могут: Проверять авторизацию (
AuthenticationMiddleware). Защищать от CSRF (
CsrfViewMiddleware). Перенаправлять запросы (
CommonMiddleware). MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
]
🟠Поиск `view` в `urls.py`
Django ищет, какая функция (
view) должна обработать этот URL. from django.urls import path
from myapp.views import hello_view
urlpatterns = [
path("hello/", hello_view), # Запрос "/hello/" попадёт в hello_view
]
🟠Выполнение `view` (контроллера)
Когда Django находит подходящее представление (
view), оно вызывается. from django.http import HttpResponse
def hello_view(request):
return HttpResponse("Привет, мир!")
🟠Формирование и обработка ответа
Django берёт
HttpResponse и передаёт его обратно через middleware (например, сжатие, защита, заголовки безопасности). HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 12
Привет, мир!
🟠WSGI/ASGI сервер отправляет ответ клиенту
На последнем этапе WSGI/ASGI-сервер отправляет ответ обратно браузеру или API-клиенту.
🚩Краткая схема обработки запроса
Клиент (браузер) → WSGI/ASGI → Django Middleware → URL Dispatcher → View → Response → Клиент
Ставь 👍 и забирай 📚 Базу знаний
🤔 Можно ли при вызове метода save указать какие поля изменять?
Да, в Django ORM можно указать конкретные поля для сохранения, используя параметр
🚩Как использовать `update_fields`
Пример модели
Обновляем только поле
🚩Что делает `update_fields`?
Генерирует SQL-запрос только для указанных полей, например:
🚩Когда `update_fields` полезен?
Уменьшает нагрузку на БД, так как обновляет только нужные поля.
Полезен, если нужно изменить одно поле, а не всю запись.
Избегает ненужных изменений в
🚩Ограничения `update_fields`
Нельзя использовать при создании объекта (
Не обновляет
Решение: обновить вручную:
Ставь 👍 и забирай 📚 Базу знаний
Да, в Django ORM можно указать конкретные поля для сохранения, используя параметр
update_fields в методе .save(). 🚩Как использовать `update_fields`
Пример модели
from django.db import models
class UserProfile(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField()
age = models.IntegerField()
Обновляем только поле
name, не трогая email и age user = UserProfile.objects.get(id=1)
user.name = "Новый пользователь"
user.save(update_fields=["name"]) # Обновит только поле `name`
🚩Что делает `update_fields`?
Генерирует SQL-запрос только для указанных полей, например:
UPDATE user_profile SET name = 'Новый пользователь' WHERE id = 1;
🚩Когда `update_fields` полезен?
Уменьшает нагрузку на БД, так как обновляет только нужные поля.
Полезен, если нужно изменить одно поле, а не всю запись.
Избегает ненужных изменений в
auto_now и auto_now_add полях (DateTimeField). 🚩Ограничения `update_fields`
Нельзя использовать при создании объекта (
save() с update_fields не работает для .create()). user = UserProfile(name="Alice", email="alice@example.com")
user.save(update_fields=["name"]) # ❌ Ошибка, объект ещё не в базе!
Не обновляет
auto_now-поля (DateTimeField) автоматически! updated_at = models.DateTimeField(auto_now=True) # Не обновится с `update_fields`
Решение: обновить вручную:
user.updated_at = timezone.now()
user.save(update_fields=["name", "updated_at"])
Ставь 👍 и забирай 📚 Базу знаний
👍2
🤔 Что такое SDLC?
Это методология управления процессом создания программного обеспечения, которая включает в себя последовательность этапов и действий, необходимых для разработки, тестирования, развертывания и поддержки программных продуктов. Цель SDLC — обеспечить структурированный и эффективный подход к разработке ПО, минимизируя риски и повышая качество конечного продукта.
🚩Основные этапы SDLC
🟠Планирование и анализ требований (Planning and Requirements Analysis)
На этом этапе определяются цели проекта, анализируются потребности и требования к системе. Включает сбор требований от заинтересованных сторон, анализ бизнес-процессов и создание документации с описанием требований.
Встречи с клиентами и пользователями для определения функций системы. Документирование функциональных и нефункциональных требований.
🟠Проектирование (Design)
На этапе проектирования разрабатывается архитектура системы и ее компоненты. Создаются технические спецификации, включая схемы базы данных, диаграммы классов и интерфейсов, а также детализируется план реализации.Разработка диаграмм UML.Создание прототипов пользовательского интерфейса.Проектирование архитектуры системы.
🟠Разработка (Implementation or Coding)
На этом этапе осуществляется непосредственная разработка программного обеспечения на основе спецификаций, созданных на предыдущем этапе. Кодирование выполняется в соответствии с выбранными языками программирования и инструментами разработки. Написание кода для модулей и компонентов системы. Интеграция различных компонентов системы. Регулярное использование систем контроля версий (например, Git).
🟠Тестирование (Testing)
Этап тестирования включает проверку и валидацию системы для обнаружения и исправления ошибок. Тестирование проводится в различных формах, включая юнит-тестирование, интеграционное тестирование, системное тестирование и приемочное тестирование. Автоматизированное тестирование с использованием фреймворков, таких как pytest или JUnit. Ручное тестирование функциональности и пользовательского интерфейса. Тестирование производительности и безопасности.
🟠Развертывание (Deployment)
На этом этапе программное обеспечение разворачивается в рабочей среде и становится доступным пользователям. Включает настройку серверов, развертывание баз данных и настройку инфраструктуры. Развертывание на облачных платформах, таких как AWS или Azure. Настройка и конфигурация серверов и сетей. Миграция данных и начальная загрузка данных.
🟠Поддержка и сопровождение (Maintenance)
Этап поддержки и сопровождения включает в себя обслуживание и улучшение системы после ее развертывания. Включает исправление ошибок, обновление функциональности и оптимизацию производительности. Обновление системы безопасности. Внесение изменений на основе отзывов пользователей. Обслуживание серверов и баз данных.
Ставь 👍 и забирай 📚 Базу знаний
Это методология управления процессом создания программного обеспечения, которая включает в себя последовательность этапов и действий, необходимых для разработки, тестирования, развертывания и поддержки программных продуктов. Цель SDLC — обеспечить структурированный и эффективный подход к разработке ПО, минимизируя риски и повышая качество конечного продукта.
🚩Основные этапы SDLC
🟠Планирование и анализ требований (Planning and Requirements Analysis)
На этом этапе определяются цели проекта, анализируются потребности и требования к системе. Включает сбор требований от заинтересованных сторон, анализ бизнес-процессов и создание документации с описанием требований.
Встречи с клиентами и пользователями для определения функций системы. Документирование функциональных и нефункциональных требований.
🟠Проектирование (Design)
На этапе проектирования разрабатывается архитектура системы и ее компоненты. Создаются технические спецификации, включая схемы базы данных, диаграммы классов и интерфейсов, а также детализируется план реализации.Разработка диаграмм UML.Создание прототипов пользовательского интерфейса.Проектирование архитектуры системы.
🟠Разработка (Implementation or Coding)
На этом этапе осуществляется непосредственная разработка программного обеспечения на основе спецификаций, созданных на предыдущем этапе. Кодирование выполняется в соответствии с выбранными языками программирования и инструментами разработки. Написание кода для модулей и компонентов системы. Интеграция различных компонентов системы. Регулярное использование систем контроля версий (например, Git).
🟠Тестирование (Testing)
Этап тестирования включает проверку и валидацию системы для обнаружения и исправления ошибок. Тестирование проводится в различных формах, включая юнит-тестирование, интеграционное тестирование, системное тестирование и приемочное тестирование. Автоматизированное тестирование с использованием фреймворков, таких как pytest или JUnit. Ручное тестирование функциональности и пользовательского интерфейса. Тестирование производительности и безопасности.
🟠Развертывание (Deployment)
На этом этапе программное обеспечение разворачивается в рабочей среде и становится доступным пользователям. Включает настройку серверов, развертывание баз данных и настройку инфраструктуры. Развертывание на облачных платформах, таких как AWS или Azure. Настройка и конфигурация серверов и сетей. Миграция данных и начальная загрузка данных.
🟠Поддержка и сопровождение (Maintenance)
Этап поддержки и сопровождения включает в себя обслуживание и улучшение системы после ее развертывания. Включает исправление ошибок, обновление функциональности и оптимизацию производительности. Обновление системы безопасности. Внесение изменений на основе отзывов пользователей. Обслуживание серверов и баз данных.
Ставь 👍 и забирай 📚 Базу знаний
🤔 Какие есть особенности исключения в Python?
В Python исключения (
Все исключения в Python — это объекты, унаследованные от
Все исключения унаследованы от
Можно перехватывать несколько исключений
Если не знаем, какая ошибка может произойти:
Можно создать свой класс ошибки, унаследованный от
Ставь 👍 и забирай 📚 Базу знаний
В Python исключения (
exceptions) — это специальные объекты, которые возникают при ошибках и прерывают выполнение программы, если их не обработать.Все исключения в Python — это объекты, унаследованные от
BaseException. try:
1 / 0
except ZeroDivisionError as e:
print(type(e)) # <class 'ZeroDivisionError'>
print(e) # division by zero
Все исключения унаследованы от
BaseException: BaseException
├── Exception
│ ├── ArithmeticError
│ │ ├── ZeroDivisionError
│ │ ├── OverflowError
│ ├── ValueError
│ ├── IndexError
│ ├── KeyError
│ ├── TypeError
├── SystemExit
├── KeyboardInterrupt
Можно перехватывать несколько исключений
try:
x = int("abc") # Ошибка ValueError
except (ValueError, TypeError) as e:
print(f"Ошибка: {e}")
Если не знаем, какая ошибка может произойти:
try:
x = 1 / 0
except Exception as e:
print(f"Ошибка: {e}") # division by zero
finally выполняется всегда try:
1 / 0
except ZeroDivisionError:
print("Ошибка!")
finally:
print("Этот код выполнится всегда")
raise позволяет выбрасывать исключения вручную raise ValueError("Ошибка: неверное значение!")Можно создать свой класс ошибки, унаследованный от
Exception: class MyError(Exception):
pass
raise MyError("Это моя ошибка!")
Ставь 👍 и забирай 📚 Базу знаний
👍3
🤔 Как импортировать модуль?
Используется ключевое слово import с указанием имени модуля. Это подключает модуль и позволяет использовать его содержимое через точку.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Используется ключевое слово import с указанием имени модуля. Это подключает модуль и позволяет использовать его содержимое через точку.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
💊5👍1🔥1
🤔 Что такое моржовый оператор?
Моржовый оператор (
🚩Как он работает?
Обычно мы записываем код так:
С
🚩Где использовать?
В циклах (избегаем лишних вычислений). Вместо:
С
В
Без
С
В списковых включениях (list comprehensions)
Без
С
🚩Когда не стоит использовать `:=`?
Если код становится сложнее для чтения
Ставь 👍 и забирай 📚 Базу знаний
Моржовый оператор (
:=) – это новый оператор, появившийся в Python 3.8, который позволяет присваивать значение переменной прямо внутри выражения. 🚩Как он работает?
Обычно мы записываем код так:
value = len(my_list) # Сначала присваиваем
if value > 10: # Потом используем
print("Список большой")
С
:= можно совместить оба действия if (value := len(my_list)) > 10:
print("Список большой")
🚩Где использовать?
В циклах (избегаем лишних вычислений). Вместо:
data = input("Введите строку: ")
while data != "exit":
print("Вы ввели:", data)
data = input("Введите строку: ")С
:= можно записать короче:while (data := input("Введите строку: ")) != "exit":
print("Вы ввели:", data)В
if и while (проверяем и присваиваем одновременно) Без
:=text = input("Введите слово: ")
if len(text) > 5:
print(f"Слово длинное ({len(text)} символов)")С
:=:if (length := len(text)) > 5:
print(f"Слово длинное ({length} символов)")
В списковых включениях (list comprehensions)
Без
:=:numbers = [random.randint(1, 100) for _ in range(10)]
filtered = [num for num in numbers if num % 2 == 0]
С
:=:filtered = [num for _ in range(10) if (num := random.randint(1, 100)) % 2 == 0]
🚩Когда не стоит использовать `:=`?
Если код становится сложнее для чтения
if (a := func()) and (b := another_func(a)) > 10:
...
Ставь 👍 и забирай 📚 Базу знаний
👍3
🤔 Два способа создания класса
В Python можно создать класс двумя основными способами:
Через
Через
🚩Обычное создание класса через `class`
Это стандартный способ, который мы используем чаще всего.
🚩Динамическое создание класса через `type()`
Функция
Ставь 👍 и забирай 📚 Базу знаний
В Python можно создать класс двумя основными способами:
Через
class (обычный способ) Через
type() (динамическое создание класса) 🚩Обычное создание класса через `class`
Это стандартный способ, который мы используем чаще всего.
class Person:
def __init__(self, name):
self.name = name
def say_hello(self):
return f"Привет, я {self.name}!"
p = Person("Алиса")
print(p.say_hello()) # Привет, я Алиса!
🚩Динамическое создание класса через `type()`
Функция
type() позволяет создать класс "на лету". Person = type("Person", (object,), {
"__init__": lambda self, name: setattr(self, "name", name),
"say_hello": lambda self: f"Привет, я {self.name}!"
})
p = Person("Боб")
print(p.say_hello()) # Привет, я Боб!Ставь 👍 и забирай 📚 Базу знаний
👍2
🤔 Что в python не является объектом?
В Python практически всё является объектом: числа, строки, функции, классы, модули и даже сам интерпретатор Python рассматривает их как объекты. Однако есть несколько вещей, которые объектами не являются:
🟠Операторы и синтаксические конструкции
Операторы (
🟠Ключевые слова (keywords)
Встроенные ключевые слова Python (
🟠Идентификаторы переменных
Хотя переменные ссылаются на объекты, сами идентификаторы (имена переменных) — это просто ссылки, а не объекты.
🟠Аннотации типов во время компиляции
Аннотации типов в Python, такие как
Ставь 👍 и забирай 📚 Базу знаний
В Python практически всё является объектом: числа, строки, функции, классы, модули и даже сам интерпретатор Python рассматривает их как объекты. Однако есть несколько вещей, которые объектами не являются:
🟠Операторы и синтаксические конструкции
Операторы (
+, -, *, and, or, not и т. д.) сами по себе не являются объектами. Они — часть синтаксиса языка и не имеют представления в виде объектов в памяти.a = 10 + 5 # Оператор "+" выполняет сложение, но сам по себе не объект
print(type(+)) # Ошибка: нельзя получить тип оператора
🟠Ключевые слова (keywords)
Встроенные ключевые слова Python (
if, else, while, for, def, class, return и т. д.) не являются объектами. Они зарезервированы интерпретатором и используются для управления потоком выполнения кода.print(type(if)) # Ошибка: ключевое слово не является объектом
🟠Идентификаторы переменных
Хотя переменные ссылаются на объекты, сами идентификаторы (имена переменных) — это просто ссылки, а не объекты.
x = 42 # x — это имя, а не объект
print(type(x)) # Это целое число, но само имя "x" объектом не является
🟠Аннотации типов во время компиляции
Аннотации типов в Python, такие как
list[str], не создают объекты во время компиляции кода. Они интерпретируются только на уровне анализа типов.def func(x: int) -> str:
return str(x)
Ставь 👍 и забирай 📚 Базу знаний
👍4
🤔 Что такое URI?
URI (Uniform Resource Identifier) — это уникальный идентификатор ресурса. Он может указывать как на место ресурса, так и просто идентифицировать его по имени. URI — более общее понятие.
Примеры:
- mailto:someone@example.com
- urn:isbn:978-3-16-148410-0
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
URI (Uniform Resource Identifier) — это уникальный идентификатор ресурса. Он может указывать как на место ресурса, так и просто идентифицировать его по имени. URI — более общее понятие.
Примеры:
- mailto:
- urn:isbn:978-3-16-148410-0
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍3
🤔 Что такое git stash?
🚩Когда это полезно?
Нужно переключиться на другую ветку, но есть незаконченные изменения. Хочешь сохранить текущую работу, но не коммитить её. Нужно экспериментировать, но без риска потерять код.
🚩Как использовать `git stash`?
Сохранить изменения в
Посмотреть список сохранённых изменений
Выведет список всех
Восстановить сохранённые изменения
ИЛИ
Удалить
🚩Пример использования
Сценарий
- Ты работаешь в ветке
- У тебя есть изменения, которые ты не хочешь коммитить.
Решение
Ставь 👍 и забирай 📚 Базу знаний
git stash — это команда в Git, которая сохраняет незакоммиченные изменения во временное хранилище (stash) и очищает рабочую директорию. 🚩Когда это полезно?
Нужно переключиться на другую ветку, но есть незаконченные изменения. Хочешь сохранить текущую работу, но не коммитить её. Нужно экспериментировать, но без риска потерять код.
🚩Как использовать `git stash`?
Сохранить изменения в
stash git stash
Посмотреть список сохранённых изменений
git stash list
Выведет список всех
stash-ов stash@{0}: WIP on main: 1234567 Добавил новую фичу
stash@{1}: WIP on dev: 89abcde Исправил багВосстановить сохранённые изменения
git stash pop # Восстановит изменения и удалит stash
ИЛИ
git stash apply # Восстановит, но stash останется в списке
Удалить
stash после применения git stash drop stash@{0} # Удалит конкретный stash
git stash clear # Удалит все stash'и🚩Пример использования
Сценарий
- Ты работаешь в ветке
main, но нужно срочно переключиться на dev. - У тебя есть изменения, которые ты не хочешь коммитить.
Решение
git stash # Сохраняем изменения
git checkout dev # Переключаемся на другую ветку
# Делаем нужную работу...
git checkout main # Возвращаемся в основную ветку
git stash pop # Восстанавливаем изменения
Ставь 👍 и забирай 📚 Базу знаний
🤔 Зачем нужны классы BaseExceptionGroup и ExceptionGroup?
В Python 3.11 были добавлены новые классы исключений
🚩Зачем нужны `BaseExceptionGroup` и `ExceptionGroup`?
Ранее в Python было возможно выбросить только одно исключение за раз, и обработка нескольких исключений одновременно требовала сложного и неочевидного кода. Например:
При работе с асинхронными функциями или потоками может возникнуть сразу несколько ошибок, и их нужно корректно обработать.
В больших приложениях или библиотеках (например, при работе с
🚩Разница между `BaseExceptionGroup` и `ExceptionGroup`
🚩Как они работают?
Классы исключений
Указать несколько ошибок одновременно.
Позволить обработчику исключений работать с каждым из них.
Результат
🚩Обработка групп исключений
При обработке
Результат
🚩Преимущества использования
➕Работа с несколькими исключениями одновременно.
Вы можете объединить связанные ошибки и передать их в одном объекте.
➕Четкое разграничение типов исключений.
Использование
➕Удобство при асинхронном программировании.
В асинхронных задачах (
➕Упрощение сложной логики.
Код становится проще и понятнее, так как не нужно вручную собирать и разбирать исключения.
🚩Когда использовать?
Когда вы работаете с несколькими задачами, которые могут порождать ошибки одновременно (например, асинхронный код).
Когда вы хотите сообщить о нескольких связанных ошибках, не выбрасывая каждую из них отдельно.
Когда требуется раздельная обработка разных типов ошибок.
Ставь 👍 и забирай 📚 Базу знаний
В Python 3.11 были добавлены новые классы исключений
BaseExceptionGroup и ExceptionGroup. Эти классы решают проблему одновременной обработки нескольких исключений, которые могут возникать в сложных ситуациях, таких как асинхронное программирование, многопоточность или обработка нескольких связанных ошибок. Давайте разберем, зачем они нужны, как их использовать и какие преимущества они дают.🚩Зачем нужны `BaseExceptionGroup` и `ExceptionGroup`?
Ранее в Python было возможно выбросить только одно исключение за раз, и обработка нескольких исключений одновременно требовала сложного и неочевидного кода. Например:
При работе с асинхронными функциями или потоками может возникнуть сразу несколько ошибок, и их нужно корректно обработать.
В больших приложениях или библиотеках (например, при работе с
asyncio) может быть необходимость передать сразу несколько исключений, которые произошли в разных местах, как единый объект.BaseExceptionGroup и его подкласс ExceptionGroup позволяют группировать несколько исключений и выбрасывать их вместе в виде одного объекта. Это делает код более читаемым, упрощает обработку и исключает необходимость ручной агрегации ошибок.🚩Разница между `BaseExceptionGroup` и `ExceptionGroup`
BaseExceptionGroup - это базовый класс для группировки исключений. Он наследуется от BaseException и, как правило, не используется напрямую.ExceptionGroup - это подкласс, который наследуется от Exception. Этот класс используется для обработки групп исключений, которые возникают при обычных ошибках в коде (не фатальных).🚩Как они работают?
Классы исключений
BaseExceptionGroup и ExceptionGroup позволяют создать "группу исключений", которая содержит несколько отдельных исключений. Это полезно, когда вам нужно:Указать несколько ошибок одновременно.
Позволить обработчику исключений работать с каждым из них.
def task_1():
raise ValueError("Ошибка в задаче 1")
def task_2():
raise TypeError("Ошибка в задаче 2")
try:
# Создаем группу исключений
raise ExceptionGroup(
"Ошибки в задачах",
[ValueError("Ошибка в задаче 1"), TypeError("Ошибка в задаче 2")]
)
except ExceptionGroup as eg:
for exc in eg.exceptions:
print(f"Обнаружено исключение: {exc}")
Результат
Обнаружено исключение: Ошибка в задаче 1
Обнаружено исключение: Ошибка в задаче 2
🚩Обработка групп исключений
При обработке
ExceptionGroup можно использовать механизм фильтрации с помощью конструкции except*. Это нововведение в Python 3.11 позволяет обрабатывать разные типы исключений внутри группы по-разному.try:
raise ExceptionGroup(
"Ошибки в задачах",
[ValueError("Ошибка 1"), TypeError("Ошибка 2"), ValueError("Ошибка 3")]
)
except* ValueError as ve:
print("Обрабатываем ValueError:", ve)
except* TypeError as te:
print("Обрабатываем TypeError:", te)
Результат
Обрабатываем ValueError: Ошибка 1
Обрабатываем ValueError: Ошибка 3
Обрабатываем TypeError: Ошибка 2
🚩Преимущества использования
➕Работа с несколькими исключениями одновременно.
Вы можете объединить связанные ошибки и передать их в одном объекте.
➕Четкое разграничение типов исключений.
Использование
except* позволяет обработать каждое исключение из группы отдельно, не теряя гибкости.➕Удобство при асинхронном программировании.
В асинхронных задачах (
asyncio) часто возникает несколько ошибок одновременно, и их можно группировать для дальнейшей обработки.➕Упрощение сложной логики.
Код становится проще и понятнее, так как не нужно вручную собирать и разбирать исключения.
🚩Когда использовать?
Когда вы работаете с несколькими задачами, которые могут порождать ошибки одновременно (например, асинхронный код).
Когда вы хотите сообщить о нескольких связанных ошибках, не выбрасывая каждую из них отдельно.
Когда требуется раздельная обработка разных типов ошибок.
Ставь 👍 и забирай 📚 Базу знаний
👍1