Выполнение HTTP-запросов в Python: практическое руководство

Раздел: Сетевое программирование -> HTTP-запросы

Основные способы выполнения 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.

Выполнение HTTP-запроса - comments

En
Make request python (python)