Перейти к основному содержимому

ДЗ 5 — Асинхронное программирование

📚 Лекция: Асинхронное программирование

Тема и дедлайн

Тема курса: модуль 6 (асинхронное программирование) Дедлайн: 23 апреля 2026, 23:59 Classroom: Принять задание


5.1 — Найди и исправь блокировки (2 балла) ★★☆

Тебе дан файл hw05/src/broken_async.py с асинхронным кодом, который содержит несколько блокирующих операций. Найди все блокировки и исправь их.

Типичные блокировки, которые нужно найти:

  • time.sleep() вместо await asyncio.sleep()
  • requests.get() вместо await session.get() (aiohttp)
  • Синхронный open() / read() вместо aiofiles
  • CPU-bound вычисление в event loop без run_in_executor

Требования:

  • Для каждой найденной блокировки — комментарий: что именно блокирует и почему это проблема
  • Исправленный код должен проходить тесты, которые проверяют что несколько корутин выполняются конкурентно (не последовательно)
Зачем это

Написать async def недостаточно — один синхронный вызов внутри корутины блокирует весь event loop. Умение находить такие места — обязательный навык.


5.2 — Асинхронное скачивание с семафором (2 балла) ★★☆

Реализуй асинхронное скачивание списка URL с ограничением конкурентности.

results = await download_all(
urls=["https://...", "https://...", ...],
dest_dir="./downloads",
max_concurrent=5, # не более 5 одновременных запросов
)
# results: {"url": True/False, ...}

Требования:

  • asyncio.Semaphore для ограничения конкурентности — обязательно
  • При ошибке скачивания (4xx, 5xx, timeout) — не падать, вернуть False для этого URL
  • Прогресс-бар через tqdm.asyncio
  • Сравнение времени: синхронное vs асинхронное скачивание тех же URL (график или таблица)
Зачем это

Semaphore в asyncio — стандартный способ не перегрузить сервер и не получить rate-limit. Встречается в любом коде, работающем с HTTP.


5.3 — Асинхронный пайплайн на генераторах (2 балла) ★★★

Реализуй пайплайн обработки данных, где каждый шаг — async-генератор. Твой вариант определяет формат входных данных:

#ИсточникФормат строки
0Лог-файл сервера[2024-01-15 10:23:45] ERROR: Connection timeout
1Поток событий (JSON lines){"event": "click", "ts": 1705312345, "user_id": "abc"}
2CSV-данные с метриками2024-01-15T10:23:45,cpu=78.5,mem=4096,disk=85.2

Пайплайн должен корректно парсить данные в соответствии с форматом твоего варианта.

async def read_chunks(filepath: str, chunk_size: int = 1024) -> AsyncIterator[bytes]:
"""Читает файл чанками асинхронно."""
...

async def parse_lines(chunks: AsyncIterator[bytes]) -> AsyncIterator[str]:
"""Собирает строки из байтовых чанков."""
...

async def filter_lines(lines: AsyncIterator[str], pattern: str) -> AsyncIterator[str]:
"""Пропускает только строки, содержащие pattern."""
...

async def batch(items: AsyncIterator[str], size: int) -> AsyncIterator[list[str]]:
"""Группирует элементы в батчи."""
...

# Пайплайн собирается так:
async def process(filepath: str, pattern: str, batch_size: int) -> None:
chunks = read_chunks(filepath)
lines = parse_lines(chunks)
filtered = filter_lines(lines, pattern)
async for b in batch(filtered, batch_size):
await save_batch(b)

Требования:

  • Каждый генератор работает лениво — не загружает весь файл в память
  • Корректные аннотации типов (AsyncIterator, AsyncGenerator)
  • Пайплайн должен работать на файле размером > 100MB без OOM
Бонус (+1 балл)

Реализуй async-скрапер, который использует этот пайплайн для обхода нескольких страниц сайта и сохранения результатов.

Зачем это

Async-генераторы — продвинутая тема, но именно они позволяют строить эффективные потоковые пайплайны. Этот паттерн используется в aiokafka, aiofiles, и любом коде с потоковой обработкой данных.


Итого

ЗадачаБаллы
5.1 Найди и исправь блокировки2
5.2 Async-скачивание с Semaphore2
5.3 Async-пайплайн на генераторах2
5.4 Бонус: скрапер+1
Итого6 + 1