Библиотека `requests` выполняет запросы последовательно -- каждый следующий начинается только после завершения предыдущего:
```
GET /products/1/ → ждём → GET /products/2/ → ждём → ...
```
Если каждый запрос занимает 200 мс, то 10 запросов -- это 2 секунды. Асинхронные запросы выполняются параллельно:
```
GET /products/1/ ┐
GET /products/2/ ├→ все выполняются одновременно → ждём всех
GET /products/3/ ┘
```
Те же 10 запросов завершаются за те же ~200 мс.
`httpx` -- это библиотека, похожая на `requests`, с поддержкой асинхронного режима. В синхронном режиме она работает так же, как `requests`:
```python
import httpx
# Синхронно -- то же самое что requests
response = httpx.get('https://apilearn.tukas.dev/api/products/')
print(response.json()['count'])
```
Для асинхронного режима используйте `AsyncClient` с `async/await`:
```python
import httpx
import asyncio
async def fetch_products():
async with httpx.AsyncClient() as client:
response = await client.get('https://apilearn.tukas.dev/api/products/')
return response.json()
asyncio.run(fetch_products())
```
`async with` открывает клиент и автоматически закрывает его по завершении блока. `await` останавливает текущую корутину, пока не придёт ответ, но не блокирует цикл событий -- поэтому другие запросы могут выполняться параллельно.
`asyncio.gather()` запускает несколько корутин одновременно и ждёт всех:
```python
results = await asyncio.gather(
client.get(url1),
client.get(url2),
client.get(url3),
)
# results -- список объектов Response в том же порядке
```
Когда использовать async:
- Много независимых запросов (все категории, все страницы, детали продуктов).
- Запросы не зависят от результатов друг друга.
- Каждый запрос имеет заметную задержку (сетевые вызовы почти всегда имеют).
Async не помогает, когда запросы последовательны по природе (например, нужен результат запроса 1, чтобы знать что спрашивать в запросе 2).
Практические примеры параллельных запросов с httpx:
Получить количество продуктов во всех категориях параллельно:
```python
import httpx
import asyncio
BASE_URL = 'https://apilearn.tukas.dev'
async def fetch_category_count(client, slug):
response = await client.get(
f'{BASE_URL}/api/products/',
params={'category': slug, 'page_size': 1},
)
return slug, response.json()['count']
async def main():
async with httpx.AsyncClient() as client:
r = await client.get(f'{BASE_URL}/api/categories/')
categories = r.json()['results']
slugs = [cat['slug'] for cat in categories]
tasks = [fetch_category_count(client, slug) for slug in slugs]
results = await asyncio.gather(*tasks)
for slug, count in results:
print(f'{slug}: {count}')
asyncio.run(main())
```
Получить несколько продуктов по id параллельно:
```python
import httpx
import asyncio
BASE_URL = 'https://apilearn.tukas.dev'
async def fetch_product(client, product_id):
response = await client.get(f'{BASE_URL}/api/products/{product_id}/')
return response.json()
async def main():
async with httpx.AsyncClient() as client:
products = await asyncio.gather(*[
fetch_product(client, i) for i in range(1, 6)
])
for p in products:
print(p['name'], p['price'])
asyncio.run(main())
```
`*[...]` распаковывает список в позиционные аргументы для `asyncio.gather`. `gather(*tasks)` эквивалентен `gather(task1, task2, task3, ...)`.
Примечание по httpx vs requests: `httpx` поддерживает и синхронный, и асинхронный режимы, имеет почти идентичный API с `requests` и поддерживает HTTP/2. Для сугубо синхронных скриптов `requests` вполне подходит. Используйте `httpx`, когда нужен async.
Сравнение httpx и requests:
```
requests httpx
Синхронный режим requests.get() httpx.get()
Асинхронный режим — httpx.AsyncClient
Сессия requests.Session httpx.Client (синх) / httpx.AsyncClient
API запросов .get .post .json() одинаковое
raise_for_status ✓ ✓
```
Параллельные запросы с asyncio.gather:
```python
# Список корутин → gather → список результатов (в том же порядке)
responses = await asyncio.gather(
client.get(url1),
client.get(url2),
)
# responses[0] соответствует url1, responses[1] — url2
```
Распаковка списка с `*`:
```python
# Вместо:
await asyncio.gather(fetch(1), fetch(2), fetch(3), fetch(4), fetch(5))
# Используйте:
await asyncio.gather(*[fetch(i) for i in range(1, 6)])
```
Когда что использовать:
```
requests Простые скрипты, последовательные запросы, небольшое количество запросов
httpx async Много независимых запросов, скорость важна
```
Используйте asyncio.gather() чтобы сделать два запроса параллельно: GET /api/products/ и GET /api/categories/. Выведите общее количество продуктов и количество категорий.
import httpx
import asyncio
BASE_URL = 'https://apilearn.tukas.dev'
async def main():
async with httpx.AsyncClient() as client:
# Сделайте оба запроса параллельно через gather
pass
asyncio.run(main())
Напишите корутину fetch_product(client, product_id), которая получает /api/products/{id}/. Используйте asyncio.gather() чтобы получить продукты с id от 1 до 5 одновременно. Выведите название и цену каждого.
import httpx
import asyncio
BASE_URL = 'https://apilearn.tukas.dev'
async def fetch_product(client, product_id):
# GET /api/products/{product_id}/
pass
async def main():
async with httpx.AsyncClient() as client:
# Соберите и выполните 5 запросов через gather
pass
asyncio.run(main())
Решение
import httpx
import asyncio
BASE_URL = 'https://apilearn.tukas.dev'
async def fetch_product(client, product_id):
response = await client.get(f'{BASE_URL}/api/products/{product_id}/')
return response.json()
async def main():
async with httpx.AsyncClient() as client:
products = await asyncio.gather(*[
fetch_product(client, i) for i in range(1, 6)
])
for p in products:
print(p['name'], p['price'])
asyncio.run(main())
Используйте httpx.AsyncClient с заголовком авторизации (полученным через синхронный requests.post). Сделайте параллельные GET к /api/cart/ и /api/users/profile/. Выведите username и количество товаров в корзине.
import httpx
import asyncio
import requests
BASE_URL = 'https://apilearn.tukas.dev'
# 1. Получите токен через requests (синхронно)
# 2. Используйте AsyncClient с заголовком Authorization
# 3. Параллельно получите профиль и корзину
Измерьте время выполнения двух подходов для получения продуктов 1-5: сначала с requests в цикле (последовательно), затем с httpx и asyncio.gather (параллельно). Выведите время для обоих вариантов.
import httpx
import asyncio
import requests
import time
BASE_URL = 'https://apilearn.tukas.dev'
# Подход 1: последовательный с requests
start = time.time()
# ... ваш код ...
print(f'Последовательный: {time.time() - start:.2f}s')
# Подход 2: параллельный с httpx
start = time.time()
# ... ваш код ...
print(f'Параллельный: {time.time() - start:.2f}s')
Решение
import httpx
import asyncio
import requests
import time
BASE_URL = 'https://apilearn.tukas.dev'
# Подход 1: последовательный
start = time.time()
for i in range(1, 6):
requests.get(f'{BASE_URL}/api/products/{i}/')
print(f'Последовательный: {time.time() - start:.2f}s')
# Подход 2: параллельный
async def fetch(client, i):
return await client.get(f'{BASE_URL}/api/products/{i}/')
async def parallel():
async with httpx.AsyncClient() as client:
await asyncio.gather(*[fetch(client, i) for i in range(1, 6)])
start = time.time()
asyncio.run(parallel())
print(f'Параллельный: {time.time() - start:.2f}s')
No split tab
Настройки cookies
Мы используем необходимые cookies для работы сайта. С вашего разрешения мы также можем сохранять настройки сайта и использовать аналитические и рекламные cookies, чтобы понимать использование сайта и поддерживать развитие проекта.
* Вы всегда можете изменить свой выбор в настройках сайта.
Выберите категории cookies
Настройки аналитики
Можно отключить аналитику использования платформы. Также можно отправить в Google Analytics запрос на удаление данных об использовании этого сайта, связанных с этим браузером.
Учебный workspace
Учитесь, читая, запуская код и решая задачи.
Практикуйте программирование с пояснениями тем, упражнениями, инструментами browser IDE, проверкой regex и тренировкой печати кода в одном workspace.
Открывайте инструменты во вкладках.Упражнения, IDE-инструменты и тренажеры остаются доступными как вкладки сайта.
Переключайтесь без потери контекста.Переходите между пояснениями, кодом и утилитами, сохраняя свое место.
Используйте sidebar как карту.Левые панели содержат навигацию, настройки, файлы, libraries и управление инструментами.
PythonJavaScriptSQLite
Одна IDE, три практичных режима
Python в браузере.Запускайте небольшие скрипты, пробуйте библиотеки и тренируйте API-запросы без установки.
JavaScript для быстрых экспериментов.Проверяйте код для браузера и сравнивайте идеи рядом с учебными материалами.
SQLite для практики с данными.Открывайте обозреватель базы данных, изучайте таблицы, пишите запросы и учитесь SQL локально.
ТемаIDE
Работайте рядом в split tabs
Держите инструкции перед глазами.Откройте упражнение или справочную страницу рядом с IDE, вместо постоянных переключений.
Сравнивайте инструменты во время обучения.Размещайте проверки regex, пояснения и эксперименты с кодом рядом, когда это нужно для задачи.
Закройте split, когда закончите.Workspace вернётся к одной сфокусированной вкладке, а открытые вкладки сайта останутся доступны.
Тренажер слепой печати кода
Или просто текста
Тренажер рассчитан на физическую клавиатуру.Откройте этот раздел на ноутбуке или компьютере с широким экраном. На телефоне тренировка слепой печати не будет корректной.
Скорость: 0 зн/мин
0 слов/мин
Лучшая скорость (60с): 0 зн/мин
0 слов/мин
Ошибки: 0
Общее время: 0.0 с
Для активации режима слепого набора не подсматривайте на физическую клавиатуру.