Python · API · Просунутий рівень
Асинхронні запити з httpx
Використовуйте httpx з asyncio для паралельних запитів до API та прискорення скриптів із кількома викликами.
Короткий вступ до теми та пояснення перед вправами (вправи нижче):
Практичні приклади asyncio.gather
#Довідник httpx та asyncio
#Вправи:
Перший асинхронний запит
#Напишіть асинхронну функцію з httpx.AsyncClient, яка отримує /api/products/ і виводить кількість продуктів. Запустіть її через asyncio.run().
import httpx
import asyncio
BASE_URL = 'https://apilearn.tukas.dev'
async def fetch_products():
# Використайте httpx.AsyncClient щоб отримати /api/products/
pass
asyncio.run(fetch_products())
Рішення
import httpx
import asyncio
BASE_URL = 'https://apilearn.tukas.dev'
async def fetch_products():
async with httpx.AsyncClient() as client:
response = await client.get(f'{BASE_URL}/api/products/')
data = response.json()
print(data['count'])
asyncio.run(fetch_products())
Паралельні запити з gather
#Використайте 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())
Рішення
import httpx
import asyncio
BASE_URL = 'https://apilearn.tukas.dev'
async def main():
async with httpx.AsyncClient() as client:
products_resp, categories_resp = await asyncio.gather(
client.get(f'{BASE_URL}/api/products/'),
client.get(f'{BASE_URL}/api/categories/'),
)
print(products_resp.json()['count'])
print(len(categories_resp.json()))
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. Паралельно отримайте профіль і кошик
Рішення
import httpx
import asyncio
import requests
BASE_URL = 'https://apilearn.tukas.dev'
token = requests.post(f'{BASE_URL}/api/auth/token/', json={
'username': 'ВАШ_ЛОГІН', 'password': 'ВАШ_ПАРОЛЬ',
}).json()['token']
async def main():
headers = {'Authorization': f'Token {token}'}
async with httpx.AsyncClient(headers=headers) as client:
profile_resp, cart_resp = await asyncio.gather(
client.get(f'{BASE_URL}/api/users/profile/'),
client.get(f'{BASE_URL}/api/cart/'),
)
print(profile_resp.json()['username'])
print(len(cart_resp.json()['items']))
asyncio.run(main())
Порівняння послідовного та паралельного виконання
#Виміряйте час виконання двох підходів для отримання продуктів 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')