Асинхронность и потоки в Python: asyncio, TaskGroup и free-threading
Зачем нужна конкурентность, async/await, TaskGroup, потоки и GIL. Для опытных: TaskGroup.cancel (3.15), free-threaded сборка (3.13–3.14), субинтерпретаторы (3.14).
- Запускать сетевые задачи конкурентно
- Управлять группой задач
- Понимать, когда нужна сборка без GIL
Phần đầu bài giảng
Три курса валют — три секунды ожидания
- Каждый запрос к API курсов ≈ 1 с ожидания сети
- Подряд: 3.0 с, вместе: 1.0 с
- Процессор всё это время простаивает
Трекер научился переводить траты в рубли, и для этого спрашивает курсы валют у внешнего сервиса: доллар, евро, юань. Каждый ответ идёт около секунды, и программа покорно ждёт их по очереди — три секунды. При этом процессор почти всё время ничего не делает: он просто ждёт ответа по сети. Если отправить три запроса одновременно и ждать их вместе, выйдет одна секунда. Как это сделать — и почему потоки здесь не единственный ответ, — разберём сегодня.
$ uv run rates_seq.py
подряд 3.0 с
$ uv run rates_async.py
вместе 1.0 с
Ждать и считать — разные задачи
- I/O-bound: сеть, диск, база — ждём ответа
- CPU-bound: расчёты — процессор занят
- Для ожидания — asyncio или потоки, для расчётов — процессы
Сначала главное различие, без которого дальше ничего не понять. Представьте повара. Если он поставил воду и ждёт кипения, он может за это время нарезать овощи, а потом поставить духовку — один повар, много дел, потому что основное время занимает ожидание. Это задачи ввода-вывода: сеть, диск, база данных. А если он вручную месит тесто, параллельно ничего не сделаешь — руки заняты. Это вычислительные задачи. Для них нужны дополнительные повара.
async и await: функция, которая умеет ждать
- async def — корутина: вызов не выполняет, а создаёт объект
- await — «подожди, а пока займись другим»
- asyncio.run(main()) — запустить цикл событий
Асинхронный код в Python строится на двух словах. Async перед def объявляет корутину — функцию, которая умеет приостанавливаться. Await внутри неё говорит: здесь я буду ждать, а ты, цикл событий, пока займись другими задачами. Тот самый повар: поставил воду, сказал await и пошёл резать овощи. Запускается всё это функцией run. Важная деталь: внутри асинхронного кода нельзя пользоваться обычным sleep или блокирующими запросами — они остановят весь цикл.
import asyncio
async def fetch_rate(currency: str) -> float:
await asyncio.sleep(1) # имитация запроса к API
return 90.0
async def main() -> None:
for cur in ["USD", "EUR", "CNY"]:
rate = await fetch_rate(cur) # ждём по очереди
print(cur, rate)
asyncio.run(main()) # ~3 секунды
Bài giảng đầy đủ dành cho thuê bao
Còn 10 slide nữa trong phiên bản đầy đủ.
Video, toàn bộ slide, ghi chú, bài kiểm tra, gia sư AI và phỏng vấn sẽ mở sau khi đăng nhập và đăng ký thuê bao.
Đăng nhập hoặc đăng ký Đăng ký thuê baoNội dung bài giảng
- Три курса валют — три секунды ожидания
- Ждать и считать — разные задачи
- async и await: функция, которая умеет ждать
- TaskGroup: запустить вместе и дождаться всех
- Ошибка в одной задаче отменяет остальные
- Грабли: забыли await
- GIL: почему потоки не ускоряют расчёты
- ❓ Стоп-проверка: что выбрать?
- 💡 Разбор: ждём — asyncio или потоки, считаем — процессы
- Что нового: TaskGroup.cancel (3.15)
- Что нового: Python без GIL (3.13–3.14, PEP 703 и 779)
- Что нового: субинтерпретаторы (3.14, PEP 734)
- Итог: курсы валют за секунду, расчёты — на всех ядрах
Bài viết liên quan đến bài học này
- Asyncio trong Python: async/await, TaskGroup, luồng, multiprocessing và GIL
- Cách tải và cài đặt Python trên Windows, macOS và Linux: hướng dẫn từng bước
- Chuỗi trong Python: split, replace, strip, join, cắt lát và f-string
- Module và package trong Python: import, pip, venv và thư viện nói đơn giản
- Cách học Python từ đầu: lộ trình học từng bước cho người mới
Tất cả bài giảng của khóa học
- Python 3.15 с нуля и для опытных: что нового и как учить
- Python 3.15: установка, REPL и первый скрипт за десять минут
- Переменные, числа и строки в Python: f-строки и t-строки
- Условия, циклы и match/case в Python: управляем ходом программы
- Списки, кортежи, словари и множества: frozendict в Python 3.15
- Comprehensions в Python: распаковка * и ** внутри (PEP 798)
- Функции и аннотации типов в Python: от def до sentinel
- Ошибки и исключения в Python 3.15: читаем трейсбек и подсказки «Did you mean»
- Модули, пакеты и ленивые импорты в Python 3.15 (PEP 810)
- Файлы, JSON и CSV в Python: pathlib и UTF-8 по умолчанию
- Классы и dataclasses в Python: ООП без лишнего кода
- Асинхронность и потоки в Python: asyncio, TaskGroup и free-threading
- Профилирование Python 3.15: Tachyon вместо cProfile и итоговый проект