en
Feedback
Python академия

Python академия

Open in Telegram

Учи Python быстро и легко. Ежедневно публикуем практические задачи, разборы, готовые решения, объяснения логики, советы по алгоритмам. ✔ Подходит для прокачки навыков кодирования. По всем вопросам @evgenycarter

Show more
7 189
Subscribers
No data24 hours
-77 days
-3930 days
Posts Archive
Проверка истинности объекта класса Для того, чтобы определить поведение при проверке на истинность объектов классов в python3
Проверка истинности объекта класса Для того, чтобы определить поведение при проверке на истинность объектов классов в python3 есть "магический" метод __bool__(), который был добавлен на замену устаревшему __nonzero__() в python2. Если данный метод определен в классе, то он будет вызываться при каждой проверке объекта на истинность а также с помощью функции bool(). Метод должен возвращать False или True. Если __bool__() не определен, будет вызываться метод __len__(), если он определен, и, соответственно, объект будет считаться истинным, если результат __len__() не будет равен нулю. Если в классе не определены ни __len__(), ни __bool__(), все его экземпляры будут истинными. 📲 Мы в MAX Подписывайтесь на канал 👉@pythonofff

Как искать индекс элемента, которого, возможно, нет в списке Бывает, нужно получить индекс элемента, но мы не уверены, есть л
Как искать индекс элемента, которого, возможно, нет в списке Бывает, нужно получить индекс элемента, но мы не уверены, есть ли он в списке. Если попытаться получить индекс элемента, которого нет в списке, метод index() вызовет ошибку ValueError. При отсутствии обработки исключений ValueError вызовет аварийное завершение программы. Такой исход явно не является хорошим и с ним нужно что-то сделать. 📲 Мы в MAX Подписывайтесь на канал 👉@pythonofff

Как найти индексы всех вхождений элемента в списке А что, если искомое значение встречается в списке несколько раз и мы хотим
Как найти индексы всех вхождений элемента в списке А что, если искомое значение встречается в списке несколько раз и мы хотим узнать индексы всех этих элементов? Метод index() выдаст нам индекс только первого вхождения. В этом фрагменте кода мы перебираем индексы списка в цикле for и при помощи range(). Далее мы проверяем значение элемента под каждым индексом на равенство «Math«. Если значение элемента — «Math«, мы сохраняем значение индекса в списке. 📲 Мы в MAX Подписывайтесь на канал 👉@pythonofff

♾️ Бесконечные аргументы: Магия Звездочек Замечали, что в функцию print() можно передать сколько угодно значений? print(1, "a", [1,2], True) - и она не ломается! Как сделать такую же всеядную функцию самому? Нам понадобятся операторы распаковки: * и **. 📦 1. *args (Позиционные аргументы) Если поставить одну звездочку перед именем аргумента (обычно называют args), Python соберет все переданные значения в кортеж (tuple).

def sum_all(*args):
    # args превратится в (1, 2, 3, 4, 5)
    print(f"Тип: {type(args)}")
    return sum(args)

print(sum_all(1, 2, 3, 4, 5)) 
# Вывод: 15

Теперь ваша функция может принимать хоть 0, хоть 100 чисел! 🗝️ 2. **kwargs (Именованные аргументы) Две звездочки (обычно kwargs - keyword arguments) собирают всё в словарь (dict). Это идеально для настроек или сложных объектов.

def create_profile(**kwargs):
    # kwargs превратится в {'name': 'Alex', 'age': 25}
    for key, value in kwargs.items():
        print(f"{key}: {value}")

create_profile(name="Alex", age=25, city="Minsk")

🔄 Обратная магия: Распаковка Звездочки работают и "на выход"! Если у вас есть список, и вы хотите передать его содержимое как отдельные аргументы:

numbers = [1, 2, 3]

# Вместо print(numbers[0], numbers[1], numbers[2])
# Пишем просто:
print(*numbers) 
# Вывод: 1 2 3

⚠️ Важно: Порядок в определении функции строгий! 1. Обычные аргументы (a, b) 2. *args 3. **kwargs Используйте это, чтобы писать гибкий код, который не нужно переписывать при каждом новом параметре! 😉 📲 Мы в MAX Подписывайтесь на канал 👉@pythonofff

Пакет со всеми алгоритмами На днях обнаружил крутой пакет, в котором реализованы практически все алгоритмы, которые можно пре
Пакет со всеми алгоритмами На днях обнаружил крутой пакет, в котором реализованы практически все алгоритмы, которые можно представить. Список всех алгоритмов с ссылками на их исходный код можете найти здесь. Такой пакет можно использовать и на практике, и как справочник на всякий случай. Например, можете посмотреть пример использования сортировки слиянием на картинке выше. 📲 Мы в MAX Подписывайтесь на канал 👉@pythonofff

🔥 БЕСПЛАТНЫЙ КУРС ПО ВРЕМЕННЫМ РЯДАМ И AI 🔥 Ищете практический и углубленный курс, чтобы освоить временные ряды? Мы создали
🔥 БЕСПЛАТНЫЙ КУРС ПО ВРЕМЕННЫМ РЯДАМ И AI 🔥 Ищете практический и углубленный курс, чтобы освоить временные ряды? Мы создали курс из 5 объемных занятий. Это именно то, что нужно, чтобы прокачаться в одной из самых востребованных аналитических областей абсолютно бесплатно! 📌 Темы занятий: 1. Основы анализа временных рядов 2. Прогнозирование на основе временных рядов с помощью AI 3. Выявление аномалий в данных с помощью нейросетей 4. Применение временных рядов в рекомендационных системах 5. Тенденции и будущее анализа временных рядов с AI Почему временные ряды? Потому что это одна из центральных тем, они отличаются тем, что: 🧬 1. Очень нужны компаниям - прям прямая необходимость 🧬 2. Очень непредсказуемые - в отличие от CV, где всё понятно, тут итоговая точность нейронки вообще непредсказуемая 🤖 Присоединяйтесь к нашему бесплатному курсу и разберитесь в этой увлекательной теме с нами!

‍Логирование Логировние является неотъемлемой частью разработки. Логи показывают информацию о текущем состоянии программы. И
Логирование Логировние является неотъемлемой частью разработки. Логи показывают информацию о текущем состоянии программы. И чем лучше выстроено логирование, тем проще будет разобраться в нестандартных ситуациях. Python поставляется для этих целей с гибким модулем logging. Для создания объекта Logger, вызываем функцию getLogger, передавая в нее имя логера. Созданный объект Logger предоставляет методы для записи сообщений разного уровня (DEBUG, INFO, WARNING, ERROR, CRITICAL), что удобно для поиска нужной информации с применением фильтров. По умолчанию в logging задан уровень WARNING, это означает, что сообщения уровня DEBUG и INFO будут игнорироваться при записи в лог. Изменить данное поведение можно с помощью метода setLevel, передав минимальный уровень, который будет отлавливаться. Для отправки логов в сконфигурированные места используются обработчики. Мы можем использовать уже существующие хэндлеры, либо создать свой класс обработчика, унаследовавшись от базового класса Handler. 📲 Мы в MAX Подписывайтесь на канал 👉@pythonofff

👨‍💻В Python-проектах со временем появляется одна и та же проблема: код работает, но становится всё сложнее поддерживать его
👨‍💻В Python-проектах со временем появляется одна и та же проблема: код работает, но становится всё сложнее поддерживать его, расширять и объяснять коллегам. Особенно в долгоживущих системах, где архитектурные решения начинают играть не меньшую роль, чем сама бизнес-логика. На открытом уроке OTUS разберём паттерны проектирования и их применение в Python-приложениях. Обсудим, какие паттерны существуют, зачем они нужны и как классические идеи объектно-ориентированного проектирования адаптируются под Python, несмотря на то, что изначально формировались для других языков. Вы поймёте, в каких задачах паттерны действительно помогают, научитесь различать основные группы паттернов и видеть их область применимости. Разберём, как использовать паттерны в Python без излишнего усложнения кода. 💥Встречаемся 10 февраля в 20:00 МСК в преддверии старта курса «Python Developer. Professional». Регистрация открыта: https://vk.cc/cU5KvC Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru

🔮 Магия Множеств: set круче списков Представьте задачу: у вас есть два списка подписчиков - из Instagram и из Telegram. 1. Нужно найти тех, кто подписан и там, и там. 2. Нужно найти тех, кто есть в Telegram, но нет в Instagram. ❌ Способ новичка (Циклы):

insta = ["max", "leo", "kate"]
tg = ["leo", "alex", "kate"]

common = []
for user in insta:
    if user in tg:
        common.append(user)

Долго, скучно, медленно (). ✅ Способ Профи (Множества): Множества в Python работают как круги Эйлера в математике.

# Создаем множества
insta = {"max", "leo", "kate"}
tg = {"leo", "alex", "kate"}

# 1. Пересечение (&) - кто есть ВЕЗДЕ
print(insta & tg)
# Вывод: {'leo', 'kate'}

# 2. Разность (-) - кто есть в TG, но НЕТ в Insta
print(tg - insta) 
# Вывод: {'alex'}

# 3. Симметричная разность (^) - уникальные для каждой платформы
print(insta ^ tg)
# Вывод: {'max', 'alex'}

💡 И самый главный трюк: Как быстро убрать дубликаты из списка? Просто превратите его в множество!

ids = [1, 2, 2, 3, 3, 3]
unique_ids = list(set(ids))
print(unique_ids) # [1, 2, 3]

🚀 Скорость: Поиск в множестве (val in my_set) происходит почти мгновенно (), в отличие от списка, который нужно перебирать целиком. Используйте силу математики, чтобы писать меньше кода! 🧠 📲 Мы в MAX Подписывайтесь на канал 👉@pythonofff

Изменение в контекстных менеджерах Как вы знаете, для удобного управления жизненным циклом ресурсов в python существуют конте
Изменение в контекстных менеджерах Как вы знаете, для удобного управления жизненным циклом ресурсов в python существуют контекстные менеджеры. Но до недавнего времени, чтобы открыть несколько ресурсов в рамках одной области видимости with нам требовалось либо прописывать их в одну строку либо использовать синтаксис переноса - обратный слеш \ (но это противоречит PEP8). С выходом python 3.10 появился новый синтаксис, позволяющий в круглых скобках указывать несколько контекстных менеджеров. А также мы можем использовать переменную созданную одним контекстным менеджером в рамках следующего за ним менеджера. Это стало возможным благодаря появлению нового синтаксического анализатора PEG в python 3.9. И, строго говоря, python 3.9 уже допускал данный синтаксис, хотя официально еще не поддерживался. 📲 Мы в MAX Подписывайтесь на канал 👉@pythonofff

🔄 Хватит писать range(len(...))! Новички часто переносят привычки из других языков в Python. Самый частый пример это циклы. ❌ Как пишет новичок: Если нужно получить элемент списка И его индекс:

names = ["Анна", "Борис", "Олег"]

# Стиль C/Java
for i in range(len(names)):
    print(f"{i}: {names[i]}")

Это работает, но выглядит громоздко и не "по-питоньи". ✅ 1. Используем enumerate Эта функция сразу выдает и счетчик, и само значение. Код становится чище!

for i, name in enumerate(names, start=1):
    print(f"{i}: {name}")

💡 Фишка: Аргумент start=1 позволяет начать нумерацию не с нуля, а с единицы (полезно для вывода списков пользователю). ❌ Как пишет новичок: Если нужно пройтись сразу по двум спискам (имена и зарплаты):

salaries = [100, 200, 300]

for i in range(len(names)):
    print(f"{names[i]} получает {salaries[i]}")

2. Используем zip Функция zip (молния 🤐) "сшивает" несколько списков в один, как застежка.

for name, salary in zip(names, salaries):
    print(f"{name} получает {salary}")

⚠️ Важно: Если списки разной длины, zip остановится, когда закончится самый короткий из них. Остальные "хвосты" будут отброшены (если не использовать zip_longest из itertools). 📲 Мы в MAX Подписывайтесь на канал 👉@pythonofff

💾 Бесконечность не предел: Магия генераторов (yield) В прошлом посте мы восхищались списковыми включениями [...]. Но у них е
💾 Бесконечность не предел: Магия генераторов (yield) В прошлом посте мы восхищались списковыми включениями [...]. Но у них есть фатальный недостаток: они создают весь список в памяти сразу. Представьте, что вам нужно обработать файл весом 10 ГБ. Если вы попытаетесь загрузить его в список read_lines(), ваш компьютер скажет "Memory Error" и программа упадет. 💥 Тут на помощь приходят Генераторы. В чем отличие? 🟢📦 Список (list): Хранит все элементы в памяти. Как готовая книга - все страницы уже напечатаны. 🟢⚙️ Генератор: Не хранит данные. Он генерирует следующее значение только тогда, когда вы его попросите. Как рассказчик, который придумывает историю на ходу. Как создать? 1. Генераторное выражение: Просто замените квадратные скобки [] на круглые ().

import sys

# Список (создает миллион чисел в памяти)
my_list = [x for x in range(1_000_000)]
print(f"List size: {sys.getsizeof(my_list)} bytes") 
# ~8 000 000 байт (8 МБ)

# Генератор (просто формула)
my_gen = (x for x in range(1_000_000))
print(f"Gen size: {sys.getsizeof(my_gen)} bytes") 
# ~100 байт (!!!)

Разница колоссальная! Генератор весит копейки, даже если в нем миллиард чисел. 2. Функция с yield: Если логика сложная, используем функцию. Вместо return (который убивает функцию и возвращает результат), пишем yield (который ставит на паузу и отдает значение).

def endless_numbers():
    n = 0
    while True: # Бесконечный цикл!
        yield n
        n += 1

# Можно брать по одному
gen = endless_numbers()
print(next(gen)) # 0
print(next(gen)) # 1
# Программа не зависнет, несмотря на while True

🚀 Итог: Если вам не нужен доступ ко всем элементам сразу (например, по индексу list[10]), а вы просто перебираете их в цикле for - всегда используйте генераторы. Знали про sys.getsizeof? Проверьте свои списки! 😉 📲 Мы в MAX Подписывайтесь на канал 👉@pythonofff

Магия одной строки: List Comprehension Вы всё еще пишете циклы для заполнения списков вот так?

squares = []
for x in range(10):
    squares.append(x ** 2)

Это работает, но это "старая школа". В Python есть способ сделать это элегантнее, быстрее и понятнее - Списковые включения. Как это выглядит: [выражение for элемент in список] Тот же самый код выше превращается в:

squares = [x ** 2 for x in range(10)]

🚀 Почему это круто? 1. Лаконичность: Меньше кода меньше багов. 2. Скорость: Это работает быстрее обычного цикла for, потому что метод .append() не вызывается на каждой итерации (оптимизация на уровне C). Уровень PRO: Добавляем условия Внутри можно использовать if, чтобы фильтровать данные на лету. Задача: Оставить только четные числа и умножить их на 10.

numbers = [1, 2, 3, 4, 5, 6]

# Читается как английское предложение:
# "x умножить на 10 для каждого x в numbers, если x четный"
result = [x * 10 for x in numbers if x % 2 == 0]

print(result) 
# [20, 40, 60]

💡 Совет: Не увлекайтесь! Если ваше выражение не влезает в одну строку или становится слишком сложным (например, вложенные циклы), лучше вернитесь к старому доброму for. Читаемость важнее понтов! Часто используете эту конструкцию? Ставьте 🔥! 📲 Мы в MAX Подписывайтесь на канал 👉@pythonofff

⚡ Lambda: Функции-однострочники В Python часто бывают ситуации, когда вам нужна маленькая функция всего один раз. Например, ч
Lambda: Функции-однострочники В Python часто бывают ситуации, когда вам нужна маленькая функция всего один раз. Например, чтобы отсортировать список по хитрому правилу. Писать для этого полноценный def, придумывать имя и занимать 3 строки кода - лень и некрасиво. Тут на сцену выходят Lambda-функции (они же анонимные функции). Синтаксис прост: lambda аргументы: выражение Сравните:

# Классический способ
def square(x):
    return x ** 2

# Lambda-стиль
sq = lambda x: x ** 2

🔥 Где это реально нужно? Чаще всего - внутри функций sorted(), min(), max(), map() или filter(). Пример из жизни: У нас есть список студентов и их баллов. Нам нужно отсортировать их не по имени, а по баллам.

students = [
    ("Антон", 50),
    ("Вика", 90),
    ("Борис", 75)
]

# Сортируем по 2-му элементу кортежа (x[1])
sorted_students = sorted(students, key=lambda x: x[1])

print(sorted_students)
# [('Антон', 50), ('Борис', 75), ('Вика', 90)]

Внутри key= мы на лету создали функцию, которая принимает студента x и возвращает его балл x[1]. sorted использует это значение для сортировки. 🛑 Когда НЕ надо использовать Lambda: Не присваивайте лямбды переменным, если планируете использовать их много раз.

# ❌ Плохо (нарушает PEP 8):
f = lambda x: x * 2

# ✅ Хорошо:
def f(x):
    return x * 2

Лямбды созданы, чтобы быть "одноразовыми"! Используете лямбды или предпочитаете старый добрый def? 👇 📲 Мы в MAX Подписывайтесь на канал 👉@pythonofff

Магия Python: Как работают декораторы? Вы постоянно видите их в коде: @bot.message_handler, @app.route, @staticmethod. Но что на самом деле делает этот символ @? В Python функции - это объекты. Их можно передавать в другие функции, как обычные переменные. Декоратор - это просто функция, которая принимает другую функцию, "обертывает" её в дополнительный код и возвращает обратно. Представьте, что у вас есть подарок (функция). Декоратор - это упаковочная бумага. Подарок внутри тот же, но теперь он выглядит и ведет себя немного иначе. Пример: Декоратор-логгер Допустим, мы хотим автоматически писать в консоль, когда функция запустилась и когда завершилась.

def my_logger(func):
    def wrapper():
        print("📢 Запускаю функцию...")
        func()  # Вызываем оригинальную функцию
        print("✅ Функция отработала!")
    return wrapper

# Применяем декоратор
@my_logger
def say_hello():
    print("Привет, мир!")

# Вызываем
say_hello()

Результат в консоли:

📢 Запускаю функцию...
Привет, мир!
✅ Функция отработала!

🤯 Что происходит под капотом? Синтаксис с @ - это просто "сахар" (упрощение). На самом деле Python делает вот это:

# Это:
@my_logger
def say_hello(): ...

# Равносильно этому:
def say_hello(): ...
say_hello = my_logger(say_hello)

А как это работает в ботах (@dp.message)? В библиотеках типа aiogram декораторы часто используются для регистрации. Когда вы пишете @dp.message(), декоратор не меняет код вашей функции, а сообщает Диспетчеру: "Эй, запомни эту функцию! Если придет сообщение, нужно запустить именно её". Итог: Декораторы нужны, чтобы добавить логику вокруг функции (проверка прав доступа, замер скорости, логирование), не меняя её код внутри. Ставь ❤️, если магия рассеялась и стало понятнее! 📲 Мы в MAX Подписывайтесь на канал 👉@pythonofff

🎛 Делаем бота удобным: Кнопки и Меню Никто не любит вводить команды вручную (/settings, /help). Пользователи любят тыкать пальцем! В Telegram есть два вида кнопок: 1. Reply-кнопки: Находятся под полем ввода. Идеальны для главного меню. 2. Inline-кнопки: Прикреплены к конкретному сообщению. Идеальны для ссылок, лайков или навигации. Давайте добавим оба вида в нашего бота! 🛠 Код:

from aiogram.types import KeyboardButton, InlineKeyboardButton
from aiogram.utils.keyboard import ReplyKeyboardBuilder, InlineKeyboardBuilder

# --- 1. Создаем Reply-клавиатуру (Главное меню) ---
def get_main_menu():
    # Инициализируем билдер
    builder = ReplyKeyboardBuilder()
    
    # Добавляем кнопки
    builder.add(KeyboardButton(text="🔥 Профиль"))
    builder.add(KeyboardButton(text="⚙️ Настройки"))
    builder.add(KeyboardButton(text="📈 Статистика"))
    
    # Настраиваем сетку: 2 кнопки в первом ряду, 1 во втором
    builder.adjust(2, 1)
    
    # resize_keyboard=True делает кнопки компактными
    return builder.as_markup(resize_keyboard=True)

# --- 2. Создаем Inline-клавиатуру (Ссылка) ---
def get_url_keyboard():
    builder = InlineKeyboardBuilder()
    builder.row(InlineKeyboardButton(
        text="↗️ Подписаться на канал", 
        url="https://t.me/pythonofff"
    ))
    return builder.as_markup()

# --- Используем в хэндлере ---
@dp.message(Command("start"))
async def cmd_start(message: types.Message):
    await message.answer(
        "Привет! Вот твое меню 👇", 
        reply_markup=get_main_menu()
    )
    
    await message.answer(
        "А это инлайн-кнопка со ссылкой:",
        reply_markup=get_url_keyboard()
    )

💡 В чем сила Builders? Метод .adjust(2, 1) позволяет одной строчкой настроить "сетку" кнопок. Раньше для этого приходилось писать сложные циклы списков! Сохраняй, чтобы не гуглить синтаксис каждый раз! 💾 📲 Мы в MAX Подписывайтесь на канал 👉@pythonofff

🤖 Твой первый Telegram-бот на aiogram Мы уже выяснили, что асинхронность это круто. А где она используется чаще всего? Конечно, в Telegram-ботах! Сегодня напишем "Эхо-бота" - это как "Hello World" в мире ботов. Он будет просто повторять всё, что мы ему напишем. 🛠 Подготовка: 1. Идем к «отцу всех ботов» - @BotFather. 2. Пишем /newbot, даем имя и юзернейм. 3. Получаем API TOKEN (длинная строка символов). 4. Устанавливаем библиотеку: pip install aiogram 💻 Код (всего 20 строк):

import asyncio
import logging
from aiogram import Bot, Dispatcher, types
from aiogram.filters import CommandStart

# Вставь сюда токен от BotFather
TOKEN = "ВАШ_ТОКЕН_ЗДЕСЬ"

# Включаем логирование, чтобы видеть ошибки в консоли
logging.basicConfig(level=logging.INFO)

# Создаем объекты бота и диспетчера
bot = Bot(token=TOKEN)
dp = Dispatcher()

# 1. Обработчик команды /start
@dp.message(CommandStart())
async def cmd_start(message: types.Message):
    await message.answer("Привет! Я твой первый бот на aiogram 🚀")

# 2. Обработчик любого текста (Эхо)
@dp.message()
async def echo_handler(message: types.Message):
    # Метод .answer() отправляет ответ в тот же чат
    await message.answer(f"Ты написал: {message.text}")

# Запуск процесса опроса (polling)
async def main():
    await dp.start_polling(bot)

if __name__ == "__main__":
    asyncio.run(main())

🧩 Разбор магии: 🟢Dispatcher (dp) - это мозг бота. Он получает сообщения от Telegram и решает, какой функции их передать. 🟢@dp.message(...) - это декораторы. Они "фильтруют" сообщения. 🟢await message.answer(...) - асинхронная отправка сообщения. Пока бот отправляет ответ тебе, он может параллельно обрабатывать сообщения от других пользователей! Скопируй, вставь токен и запусти. Поздравляю, ты только что создал своего бота! 🎉 📲 Мы в MAX Подписывайтесь на канал 👉@pythonofff

🚀 Синхронность vs Асинхронность: Ускоряем код в 10 раз Представьте, что вы стоите в очереди в Макдональдс. 🐢 Синхронный под
🚀 Синхронность vs Асинхронность: Ускоряем код в 10 раз Представьте, что вы стоите в очереди в Макдональдс. 🐢 Синхронный подход (как requests): Кассир принимает ваш заказ, уходит на кухню, ждет, пока пожарится картошка, наливает колу, отдает заказ вам и только потом обращается к следующему человеку в очереди. Медленно? Ужасно медленно! ⚡️ Асинхронный подход (как aiohttp): Кассир принимает заказ, кричит на кухню "Свободная касса!" и сразу берет заказ у следующего, пока ваш готовится. Работа идет параллельно. В Python для этого используется библиотека aiohttp и ключевые слова async / await. Сравним на практике: Допустим, нам нужно скачать 10 страниц.

import asyncio
import aiohttp
import time

# Функция для одного запроса
async def fetch_page(session, url):
    async with session.get(url) as response:
        return response.status

async def main():
    urls = ["https://google.com" for _ in range(10)] # 10 запросов
    
    async with aiohttp.ClientSession() as session:
        tasks = []
        for url in urls:
            # Создаем задачи, но еще не запускаем их ожидание
            tasks.append(fetch_page(session, url))
        
        # Запускаем все задачи одновременно!
        await asyncio.gather(*tasks)

start = time.time()
# Запуск асинхронного цикла
asyncio.run(main()) 
print(f"Время выполнения: {time.time() - start:.2f} сек")

Результат: Если requests будет делать это ~10 секунд (по 1 сек на запрос), то aiohttp справится за ~1.2 секунды. Он просто отправит все 10 запросов разом и будет ждать ответы. 🛠 Установка: pip install aiohttp ⚠️ Важно: Не используйте это для атак на сайты (DDoS). Сервер может забанить вас за слишком большое количество запросов в секунду. Сохраняй, пригодится для парсинга больших объемов данных! 🔥 📲 Мы в MAX Подписывайтесь на канал 👉@pythonofff

🛑 Твой код завис навсегда? Исправляем! Знаете ли вы, что по умолчанию библиотека requests ждет ответа от сервера бесконечно?
🛑 Твой код завис навсегда? Исправляем! Знаете ли вы, что по умолчанию библиотека requests ждет ответа от сервера бесконечно? Если сервер, к которому вы обращаетесь, "упал" или просто завис, ваш Python-скрипт тоже встанет и будет висеть вечно, пока вы не убьете процесс вручную. В продакшене (да и в пет-проектах) это недопустимо! 🚫 ✅ Решение: Всегда используйте timeout Параметр timeout указывает, сколько секунд ждать ответа, прежде чем выбросить ошибку и продолжить работу. Пример безопасного кода:

import requests
from requests.exceptions import Timeout, ConnectionError

url = "https://httpbin.org/delay/5"  # Сервер ответит через 5 сек

try:
    # Ставим таймаут 2 секунды.
    # Если сервер не ответит за 2 сек — скрипт не зависнет!
    response = requests.get(url, timeout=2)
    response.raise_for_status() # Проверка на ошибки 4xx/5xx
    print("Успех:", response.json())

except Timeout:
    print("⏰ Ошибка: Сервер отвечает слишком долго!")
except ConnectionError:
    print("🔌 Ошибка: Нет интернета или сайт недоступен.")
except Exception as e:
    print(f"Что-то пошло не так: {e}")

💡 Совет: Хорошей практикой считается ставить таймаут в диапазоне 3–10 секунд для обычных запросов. Проверьте свои старые проекты, есть ли там timeout? Если нет, самое время добавить! 👨‍💻 📲 Мы в MAX Подписывайтесь на канал 👉@pythonofff

🚀 Ускоряем массовые запросы: Sessions Представьте, что вам нужно скачать 100 страниц сайта. Если делать это через обычный requests.get(), каждый раз будет происходить следующее: 1. Открытие соединения (TCP Handshake). 2. Настройка шифрования (SSL/TLS). 3. Отправка данных. 4. Закрытие соединения. Это очень долго! 🐢 Решение: Session Сессия позволяет переиспользовать одно и то же соединение для множества запросов. Это дает огромный прирост скорости. Пример:

import requests

# Создаем сессию
with requests.Session() as s:
    # Можно сразу настроить заголовки для всех запросов
    s.headers.update({'User-Agent': 'my-app/0.0.1'})

    for i in range(5):
        # Используем s.get вместо requests.get
        r = s.get(f"https://httpbin.org/get?page={i}")
        print(f"Запрос {i} выполнен!")

💡Сессия также запоминает куки (cookies). Если вы авторизовались на сайте в первом запросе, сессия "запомнит" это для следующих. Используйте сессии, если делаете больше двух запросов к одному сайту! 📲 Мы в MAX Подписывайтесь на канал 👉@pythonofff