0Pricing
AI Agents · Урок

Обработка ответов API и ошибок

Разбор ответов JSON, кодов ошибок и шаблонов обработки исключений.

«Обработка ответов API и ошибок» — бесплатный урок AI Agents на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения AI Agents, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс AI Agents содержит 4 уроков всего.

Объект ответа

Каждый вызов requests возвращает объект ответа. Он содержит всё, что сервер отправил в ответ: код состояния, заголовки и тело. Перед обработкой тела всегда проверяйте код состояния: ответ со статусом 500 всё ещё содержит тело, но в нём не будет нужных Вам данных.

import requests

response = requests.get('https://api.example.com/data')

# Key attributes of the response
print(response.status_code)       # e.g. 200
print(response.headers)           # dict of response headers
print(response.headers.get('Content-Type'))  # 'application/json'
print(response.text)              # raw response body as string
print(response.content)           # raw bytes

Разбор JSON с помощью response.json()

Вызовите response.json(), чтобы автоматически разобрать тело ответа как JSON в словарь или список Python. Это эквивалентно json.loads(response.text), но дополнительно проверяет соответствие типа содержимого.

Вызывайте .json(), только если уверены, что ответ действительно содержит JSON: сначала проверьте заголовок Content-Type.

import requests

response = requests.get(
    'https://api.example.com/users/42',
    headers={'Authorization': 'Bearer YOUR_KEY'}
)

# Parse JSON body
user = response.json()

# Access fields safely with .get()
name = user.get('name', 'Unknown')
email = user.get('email', '')
roles = user.get('roles', [])

print(f'User: {name} ({email})')
print(f'Roles: {roles}')

Проверка кода состояния перед разбором

Никогда не вызывайте response.json(), предварительно не убедившись, что запрос выполнен успешно. Ответы с ошибками (4xx/5xx) часто содержат подробности ошибки в формате JSON — это полезно для отладки, но это не те данные, которые Вам нужны. Сначала всегда проверяйте код состояния.

import requests

response = requests.post(
    'https://api.example.com/tasks',
    json={'title': 'Write report'},
    headers={'Authorization': 'Bearer YOUR_KEY'}
)

if response.status_code == 201:
    task = response.json()
    print('Task created, ID:', task['id'])
elif response.status_code == 400:
    error = response.json()
    print('Validation error:', error.get('message'))
elif response.status_code == 401:
    print('Auth failed — check your token')
else:
    print(f'Unexpected status {response.status_code}: {response.text[:200]}')

raise_for_status() — автоматическое создание исключений при ошибках

response.raise_for_status() автоматически вызывает исключение HTTPError, если код состояния равен 4xx или 5xx. Это удобный способ преобразовать некорректные ответы HTTP в исключения Python и использовать конструкцию try/except вместо длинных цепочек if/elif.

import requests
from requests.exceptions import HTTPError

try:
    response = requests.get(
        'https://api.example.com/users/9999',
        headers={'Authorization': 'Bearer YOUR_KEY'}
    )
    response.raise_for_status()  # raises if status >= 400
    user = response.json()
    print('Found user:', user['name'])

except HTTPError as e:
    print(f'HTTP error: {e.response.status_code}')
    print('Details:', e.response.text[:300])

Обработка ошибки разбора JSON

Иногда API возвращает ответ не в формате JSON, хотя Вы его ожидаете: страницу ошибки сервера в формате HTML, пустое тело или двоичный файл. Вызов response.json() для таких ответов вызывает исключение json.JSONDecodeError. Всегда перехватывайте это исключение, чтобы агент не завершился незаметно.

import requests
import json

response = requests.get(
    'https://api.example.com/report',
    headers={'Authorization': 'Bearer YOUR_KEY'}
)

try:
    data = response.json()
except json.JSONDecodeError as e:
    print(f'Response is not valid JSON: {e}')
    print('Content-Type:', response.headers.get('Content-Type'))
    print('First 200 chars:', response.text[:200])
    # Decide: is this an HTML error page? A CSV file?
    data = None

if data is None:
    print('Falling back to text processing')

ConnectionError — проблемы с сетью

ConnectionError возникает, когда агент вообще не может связаться с сервером: например, при сбое разрешения DNS, отключённом сервере или блокировке запроса брандмауэром. Это сбой на уровне сети, произошедший ещё до установления соединения HTTP.

В отличие от ошибки 5xx, это не ответ сервера: соединение вообще не было установлено.

import requests
from requests.exceptions import ConnectionError

try:
    response = requests.get('https://api.example.com/data')
    data = response.json()
except ConnectionError as e:
    print('Cannot reach server. Possible causes:')
    print('- DNS failure (bad hostname)')
    print('- Server is down')
    print('- No internet connection')
    print('- Firewall blocking the port')
    print(f'Error detail: {e}')
    # Consider: queue the request for retry when connectivity returns

Время ожидания — защита от зависания агентов

По умолчанию requests бесконечно ждёт ответа. Медленный сервер или сервер, переставший отвечать, может навсегда заблокировать агента. Всегда задавайте время ожидания: кортеж (connect_timeout, read_timeout) в секундах. Если сервер не ответит вовремя, будет вызвано исключение Timeout.

import requests
from requests.exceptions import Timeout

try:
    response = requests.get(
        'https://api.example.com/slow-endpoint',
        headers={'Authorization': 'Bearer YOUR_KEY'},
        timeout=(5, 30)  # 5s to connect, 30s to read
    )
    data = response.json()
except Timeout:
    print('Request timed out after 30 seconds')
    print('Options: retry, use cached result, or alert operator')

Комплексная обработка исключений

В рабочих агентах перехватывайте все исключения requests в единой иерархии. requests.exceptions.RequestException — базовый класс для всех ошибок библиотеки запросов; его перехват обеспечивает защиту от непредвиденных проблем с сетью.

import requests
import json
from requests.exceptions import (
    ConnectionError, Timeout, HTTPError, RequestException
)

def safe_api_call(url, headers):
    try:
        r = requests.get(url, headers=headers, timeout=(5, 30))
        r.raise_for_status()
        return r.json()
    except Timeout:
        print('ERROR: Request timed out')
    except ConnectionError:
        print('ERROR: Cannot reach server')
    except HTTPError as e:
        print(f'ERROR: HTTP {e.response.status_code}')
        try:
            print('API error:', e.response.json().get('message'))
        except json.JSONDecodeError:
            print('Non-JSON error body')
    except RequestException as e:
        print(f'ERROR: Unexpected request error: {e}')
    return None

Ведение журналов ответов для отладки

Когда агент работает неправильно, Вам нужен достаточный контекст для диагностики. Записывайте в журнал метод запроса, URL, код состояния и важные сведения об ответе, но никогда не записывайте ключи API. В рабочих агентах используйте встроенный модуль Python logging, а не инструкции print.

import logging
import requests

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('agent.api')

def logged_request(method, url, **kwargs):
    logger.info(f'-> {method.upper()} {url}')
    response = requests.request(method, url, **kwargs)
    logger.info(
        f'<- {response.status_code} '
        f'({len(response.content)} bytes) '
        f'{response.elapsed.total_seconds():.2f}s'
    )
    if response.status_code >= 400:
        logger.error(f'Error body: {response.text[:500]}')
    return response

Обработка постраничных ответов

Многие API возвращают данные по страницам. Агент должен переходить по ссылкам пагинации, чтобы получить все результаты. Ищите в ответе URL next или поле page/cursor и повторяйте запросы, пока страницы не закончатся.

import requests

def get_all_items(base_url, headers):
    all_items = []
    url = f'{base_url}/items?page=1&limit=100'

    while url:
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        data = response.json()

        all_items.extend(data.get('items', []))

        # Follow 'next' link if present
        url = data.get('next_page_url')  # None stops the loop

        print(f'Fetched {len(all_items)} items so far...')

    print(f'Total: {len(all_items)} items')
    return all_items

Потоковая передача больших ответов

Для больших ответов (файлов и длинных ответов ИИ) используйте stream=True, чтобы не загружать весь ответ в память сразу. Считывайте ответ фрагментами. Это особенно важно, когда агент обрабатывает большие наборы данных или передаёт текст, созданный ИИ, в потоковом режиме.

import requests

response = requests.get(
    'https://api.example.com/large-report',
    headers={'Authorization': 'Bearer YOUR_KEY'},
    stream=True
)

response.raise_for_status()

# Write streamed content to file
with open('report.json', 'wb') as f:
    for chunk in response.iter_content(chunk_size=8192):
        if chunk:
            f.write(chunk)

print('Download complete')

# For streaming JSON lines (NDJSON):
for line in response.iter_lines():
    if line:
        import json
        record = json.loads(line)
        print(record)

Быстрая проверка: raise_for_status

Проверьте, насколько хорошо Вы понимаете обработку ошибок в ответах.

Итоги обработки ответов

Надёжная обработка ответов отличает хрупкого агента от надёжного:

  • Всегда проверяйте status_code перед разбором тела
  • Используйте response.json() для разбора и перехватывайте JSONDecodeError, если тело может быть не в формате JSON
  • Используйте raise_for_status(), чтобы преобразовывать ошибки HTTP в исключения
  • Перехватывайте ConnectionError при сбоях сети и Timeout при медленной работе серверов
  • Всегда задавайте кортеж timeout=(connect, read) для каждого запроса
  • Записывайте запросы и ответы в журнал (без ключей), чтобы упростить отладку

Часто задаваемые вопросы

Урок «Обработка ответов API и ошибок» бесплатный?

Да — полный текст урока «Обработка ответов API и ошибок» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс AI Agents, подпишись на CoddyKit PRO. Курс AI Agents содержит 4 уроков всего.

Чему я научусь в уроке «Обработка ответов API и ошибок»?

Разбор ответов JSON, кодов ошибок и шаблонов обработки исключений. Ты практикуешь AI Agents с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать AI Agents?

Предыдущий опыт не требуется. AI Agents на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Обработка ответов API и ошибок»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке AI Agents?

Да. Каждый урок AI Agents включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Основы REST API для разработчиков агентов
  2. Аутентификация: ключи API и OAuth
  3. Обработка ответов API и ошибок
  4. Ограничение частоты запросов и логика повторных попыток
← Назад к AI Agents