Бібліотека `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 с
Щоб тренувати сліпий друк, не підглядайте на фізичну клавіатуру.