Выполнение HTTP-запросов в Python: практическое руководство
Основные способы выполнения HTTP-запросов в Python
Для отправки HTTP-запросов в Python существует несколько библиотек. Наиболее популярным и удобным решением является библиотека requests. Однако в зависимости от ограничений проекта могут потребоваться встроенные средства или асинхронные подходы. Ниже рассмотрены ключевые варианты.
Как выполнить HTTP-запрос с помощью библиотеки requests?
Библиотека requests предоставляет простой интерфейс для всех распространённых методов HTTP. Она автоматически обрабатывает кодировку, таймауты, cookies и сессии.
import requests
# GET-запрос
response = requests.get('https://api.example.com/data')
print(response.status_code)
print(response.json())
запрос страницы python (запрос веб-страницы в python)
Для отправки POST-запроса с JSON-данными используется параметр json:
import requests
payload = {'key': 'value'}
response = requests.post('https://api.example.com/submit', json=payload)
print(response.text)
Python requests (библиотека requests в python)
Возможные проблемы
- ConnectionError – неверный адрес или отсутствие сети. Решение: проверьте URL и интернет-соединение.
- Timeout – сервер не ответил вовремя. Устанавливайте параметр timeout.
- HTTPError – код ответа 4xx или 5xx. Используйте response.raise_for_status() для проверки.
Как отправить GET-запрос с помощью urllib.request?
Встроенный модуль urllib.request позволяет выполнять HTTP-запросы без установки сторонних пакетов. Его интерфейс более низкоуровневый, чем у requests.
from urllib.request import urlopen
from urllib.parse import urlencode
params = {'q': 'python', 'page': 1}
url = 'https://api.example.com/search?' + urlencode(params)
with urlopen(url) as response:
data = response.read().decode('utf-8')
print(data)
Python urllib3 request (использование urllib3 для запросов)
Для POST нужно передать данные в теле запроса:
from urllib.request import Request, urlopen
from urllib.parse import urlencode
url = 'https://api.example.com/submit'
data = urlencode({'name': 'John'}).encode()
req = Request(url, data=data, method='POST')
with urlopen(req) as response:
print(response.read().decode())
Http error requests python (обработка http ошибок в requests)
Частые ошибки
- URLError – проблема с URL или сетью. Используйте блок try/except.
- Кодировка данных – необходимо вручную кодировать параметры и тело запроса.
- Отсутствие обработки JSON – декодирование выполняется вручную через json.loads.
Как использовать модуль http.client для низкоуровневых запросов?
http.client (или httplib в Python 2) предоставляет минимальные средства для работы с HTTP. Подход подходит, когда нужен полный контроль над процессом.
import http.client
conn = http.client.HTTPSConnection('api.example.com')
conn.request('GET', '/data')
response = conn.getresponse()
print(response.status, response.reason)
data = response.read().decode()
print(data)
conn.close()
Make request python (выполнение http-запроса)
POST-запрос с заголовками:
import http.client
import json
conn = http.client.HTTPSConnection('api.example.com')
headers = {'Content-Type': 'application/json'}
body = json.dumps({'key': 'value'})
conn.request('POST', '/submit', body=body, headers=headers)
response = conn.getresponse()
print(response.read().decode())
conn.close()
Python request files file name (отправка файла через requests)
Типичные сложности
- Необходимость ручного управления соединением (открытие/закрытие).
- Обработка chunked-передачи данных – требуется дополнительный код.
- Отсутствие автоматического следования редиректам.
Как выполнять асинхронные HTTP-запросы с aiohttp?
Для асинхронного ввода-вывода в Python используется библиотека aiohttp. Она позволяет выполнять множество запросов параллельно, что повышает производительность в I/O-задачах.
import aiohttp
import asyncio
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
async with aiohttp.ClientSession() as session:
html = await fetch(session, 'https://example.com')
print(len(html))
asyncio.run(main())
Python request params (параметры запроса)
Параллельные запросы:
import aiohttp
import asyncio
async def main():
urls = ['https://httpbin.org/get'] * 5
async with aiohttp.ClientSession() as session:
tasks = [session.get(url) for url in urls]
responses = await asyncio.gather(*tasks)
for resp in responses:
print(resp.status)
resp.close()
asyncio.run(main())
Python request download (скачивание файла через requests)
Проблемы и их решение
- RuntimeError – неправильный запуск асинхронной функции. Используйте asyncio.run().
- Утечка соединений – всегда используйте async with для сессии и ответов.
- Сложность отладки – асинхронный код труднее тестировать.
Как применять httpx для современных HTTP-запросов?
Библиотека httpx поддерживает как синхронный, так и асинхронный режимы, а также HTTP/2. Она предлагает интерфейс, похожий на requests, но с дополнительными возможностями.
import httpx
# Синхронный GET
response = httpx.get('https://api.example.com/data')
print(response.json())
# Асинхронный GET
async def async_request():
async with httpx.AsyncClient() as client:
resp = await client.get('https://api.example.com/data')
return resp.json()
import asyncio
result = asyncio.run(async_request())
print(result)
Трудности при работе с httpx
- Совместимость с некоторыми серверами, не поддерживающими HTTP/2 – отключайте этот протокол параметром http2=False.
- Необходимость установки отдельной библиотеки (pip install httpx).
- Потенциальные конфликты с asyncio при смешивании синхронного и асинхронного кода.
Расширенные примеры выполнения HTTP-запросов
1. Использование сессий в requests для сохранения cookies
Сессия позволяет автоматически управлять cookies и повторно использовать соединение.
import requests
session = requests.Session()
session.get('https://httpbin.org/cookies/set?name=value')
response = session.get('https://httpbin.org/cookies')
print(response.json())
{'cookies': {'name': 'value'}}
2. Загрузка файла с прогресс-баром (requests + tqdm)
import requests
from tqdm import tqdm
url = 'https://example.com/largefile.zip'
response = requests.get(url, stream=True)
total_size = int(response.headers.get('content-length', 0))
with open('file.zip', 'wb') as f:
for chunk in tqdm(response.iter_content(chunk_size=8192), total=total_size//8192, unit='KB'):
f.write(chunk)
Результат: файл загружается с отображением индикатора прогресса.
3. Аутентификация через Bearer токен (httpx)
import httpx
token = 'your_token_here'
headers = {'Authorization': f'Bearer {token}'}
response = httpx.get('https://api.example.com/secure', headers=headers)
print(response.status_code, response.json())
4. Параллельные асинхронные запросы с aiohttp и ограничением количества одновременных соединений
import aiohttp
import asyncio
from aiohttp import TCPConnector
async def bounded_fetch(sem, session, url):
async with sem:
async with session.get(url) as response:
return await response.text()
async def main():
urls = ['https://httpbin.org/delay/1'] * 10
sem = asyncio.Semaphore(3) # не более 3 одновременных запросов
connector = TCPConnector(limit=5)
async with aiohttp.ClientSession(connector=connector) as session:
tasks = [bounded_fetch(sem, session, url) for url in urls]
results = await asyncio.gather(*tasks)
print(f'Получено {len(results)} ответов')
asyncio.run(main())
Результат: все запросы выполняются, но одновременно не более 3.
5. Отправка формы (multipart/form-data) с файлами с помощью requests
import requests
files = {'file': ('report.xlsx', open('report.xlsx', 'rb'), 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')}
response = requests.post('https://httpbin.org/post', files=files)
print(response.json()['files'])
{'file': '... base64 encoded content ...'}
6. Обработка таймаутов и повторные попытки (retry) с использованием urllib3
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
session = requests.Session()
retries = Retry(total=3, backoff_factor=1, status_forcelist=[500, 502, 503, 504])
adapter = HTTPAdapter(max_retries=retries)
session.mount('https://', adapter)
response = session.get('https://httpbin.org/status/500')
print(response.status_code)
После трёх попыток с задержкой будет выброшено исключение, если сервер продолжает возвращать 500.