AI Agents · レッスン

APIレスポンスとエラーの処理

JSONレスポンスの解析、エラーコード、例外処理のパターンを学びます。

レッスン 3/413 ステップ

「APIレスポンスとエラーの処理」はCoddyKit上の無料AI Agentsレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAI Agents学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 AI Agentsコースには全4レッスンが含まれています。

レスポンスオブジェクト

すべてのrequests呼び出しは、Responseオブジェクトを返します。これには、ステータスコード、ヘッダー、本文など、サーバーが返したすべての情報が含まれます。本文を処理する前に、必ずステータスコードを確認してください。ステータス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

response.json()でJSONを解析する

response.json()を呼び出すと、レスポンス本文がJSONとして自動的に解析され、Pythonのdictまたはlistになります。これはjson.loads(response.text)と同等ですが、Content-Typeが適切かどうかも検証します。

レスポンスが実際に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}')

解析前にstatus_codeを確認する

リクエストが成功したことを確認せずに、response.json()を呼び出してはいけません。エラーレスポンス(4xx/5xx)には、デバッグに役立つJSON形式のエラー詳細が含まれていることもありますが、それは必要なデータではありません。必ず最初にstatus_codeを確認してください。

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()は、ステータスコードが4xxまたは5xxの場合にHTTPError例外を自動的に発生させます。これは不正なHTTPレスポンスをPythonの例外に変換する簡潔な方法であり、長いif/elifの連鎖ではなくtry/exceptを使用できるようになります。

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])

JSONDecodeErrorを処理する

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

Timeout — エージェントの停止を防ぐ

デフォルトでは、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は、requestsのすべてのエラーの基底クラスです。これを捕捉することで、予期しないネットワーク問題に対する安全網になります。

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キーは決してログに記録しないでください。本番環境のエージェントでは、print文ではなくPython組み込みのloggingモジュールを使用します。

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は、データを複数のページに分けて返します。エージェントは、すべての結果を取得するためにページネーションのリンクをたどる必要があります。レスポンス内のnext URL、または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

大きなレスポンスをストリーミングする

大きなレスポンス(ファイルや長いAI出力など)には、stream=Trueを使用して、レスポンス全体を一度にメモリへ読み込まないようにします。レスポンスをチャンク単位で読み取ってください。エージェントが大規模なデータセットを処理したり、AIが生成したテキストをストリーミングしたりする場合に不可欠です。

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()で解析し、本文がJSONでない可能性がある場合はJSONDecodeErrorを捕捉する
  • raise_for_status()を使用して、HTTPエラーを例外に変換する
  • ネットワーク障害にはConnectionErrorを、サーバーの応答が遅い場合にはTimeoutを捕捉する
  • すべてのリクエストにtimeout=(connect, read)タプルを必ず設定する
  • デバッグ可能性を高めるため、キーを含めずにリクエストとレスポンスをログに記録する
無料で開始

AI チューターと学ぶ AI Agents — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
60
レッスン
239

よくある質問

「APIレスポンスとエラーの処理」レッスンは無料ですか?

はい。「APIレスポンスとエラーの処理」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、AI Agentsコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 AI Agentsコースには全4レッスンが含まれています。

「APIレスポンスとエラーの処理」で何を学びますか?

JSONレスポンスの解析、エラーコード、例外処理のパターンを学びます。 ブラウザで直接実行するハンズオンコードでAI Agentsを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

AI Agentsを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのAI Agentsは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「APIレスポンスとエラーの処理」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このAI Agentsレッスンでコードを書いて実行できますか?

はい。すべてのAI Agentsレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. エージェント開発者のためのREST API基礎
  2. 認証:API KeysとOAuth
  3. APIレスポンスとエラーの処理
  4. レート制限とリトライロジック
← AI Agentsに戻る