You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从requests.exceptions.RequestException获取异常信息及日志最佳实践

Hey there! Let's break down your questions about handling requests exceptions in Flask step by step—this is such a common scenario when working with external APIs, so great call asking about best practices.

1. Extracting Error Messages & Context from RequestException

First off, getting the core error message is straightforward: just use str(e) or e.args[0] (since most exceptions store their message in the first argument). But RequestException and its subclasses often carry extra context you’ll want to log too:

  • Request details: Most subclasses have a request attribute that lets you access the original URL, HTTP method, headers, etc.
  • Response details: If the exception is tied to a server response (like HTTPError), you’ll get a response attribute with status code, response body, headers, etc.

Here’s a quick example of extracting all relevant info:

import requests
from requests.exceptions import RequestException

try:
    response = requests.get("https://example.invalid/api")
except RequestException as e:
    # Core error message
    error_msg = str(e)
    
    # Grab request context if available
    request_context = {}
    if hasattr(e, "request"):
        request_context["url"] = e.request.url
        request_context["method"] = e.request.method
    
    # Grab response context if available (e.g., for HTTPError)
    response_context = {}
    if hasattr(e, "response"):
        response_context["status_code"] = e.response.status_code
        response_context["response_body"] = e.response.text[:200]  # Truncate long bodies
    
    # Combine everything for logging
    full_error = f"Request failed: {error_msg}"
    if request_context:
        full_error += f" | Request: {request_context['method']} {request_context['url']}"
    if response_context:
        full_error += f" | Status Code: {response_context['status_code']}"
    
    print(full_error)  # Replace with proper logging later!
2. Differentiating Between RequestException Subclasses

RequestException is the parent class for all requests-specific errors, so catching it alone lumps together a bunch of different issues (timeouts, connection failures, HTTP 4xx/5xx errors, etc.). The best approach is to catch specific subclasses first, then use RequestException as a final fallback.

Here’s how to structure your try/except block to handle different error types:

try:
    response = requests.get("https://example.com/api")
    response.raise_for_status()  # Triggers HTTPError for 4xx/5xx responses
except requests.exceptions.HTTPError as e:
    # Handle HTTP errors (e.g., 401 Unauthorized, 500 Server Error)
    log.error(f"HTTP Error: {str(e)} | Status Code: {e.response.status_code} | URL: {e.request.url}")
    # Maybe add logic here like retrying for 5xx errors, or redirecting users for 401
except requests.exceptions.ConnectionError as e:
    # Handle connection issues (DNS failure, refused connection, network down)
    log.error(f"Connection Failure: {str(e)} | URL: {e.request.url if hasattr(e, 'request') else 'Unknown'}")
except requests.exceptions.Timeout as e:
    # Handle timeouts (connect timeout or read timeout)
    log.error(f"Request Timed Out: {str(e)} | URL: {e.request.url if hasattr(e, 'request') else 'Unknown'}")
    # Maybe add retry logic here for transient timeouts
except requests.exceptions.TooManyRedirects as e:
    # Handle excessive redirect loops
    log.error(f"Too Many Redirects: {str(e)} | URL: {e.request.url}")
except requests.exceptions.RequestException as e:
    # Catch-all for any other requests-related error
    log.error(f"Unexpected Request Failure: {str(e)}")

This way, you can tailor your handling to each error type—like retrying timeouts, alerting on connection failures, or handling authentication for 401s.

3. Best Logging Practices (Ditch print!)

Print statements are fine for local testing, but they’re useless in production—you need structured, persistent logging. Flask integrates seamlessly with Python’s built-in logging module, which is the standard for this.

Step 1: Configure Your Logger

Set up your logger once when your Flask app starts to define where logs go (file, console, etc.) and how they’re formatted:

import logging
from flask import Flask

app = Flask(__name__)

# Configure logging
logging.basicConfig(
    level=logging.ERROR,  # Log errors and above; adjust to INFO/WARNING if needed
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    handlers=[
        logging.FileHandler("app_errors.log"),  # Log to a file
        logging.StreamHandler()  # Also log to the console for local debugging
    ]
)

# Get a logger instance for your module
log = logging.getLogger(__name__)

Step 2: Log with Context

When logging exceptions, include as much context as possible (URL, method, user ID if applicable) and use exc_info=True to capture the full stack trace—this is a lifesaver for debugging:

@app.route("/fetch-external-data")
def fetch_external_data():
    try:
        response = requests.get("https://example.com/api")
        response.raise_for_status()
        return response.json()
    except requests.exceptions.HTTPError as e:
        log.error(
            f"HTTP Error fetching data: {str(e)} | Status Code: {e.response.status_code} | URL: {e.request.url}",
            exc_info=True
        )
        return {"error": "Failed to retrieve data"}, 500
    except requests.exceptions.RequestException as e:
        log.error(
            f"Request failed: {str(e)} | URL: {e.request.url if hasattr(e, 'request') else 'Unknown'}",
            exc_info=True
        )
        return {"error": "Service unavailable"}, 503

Bonus Production Tips

  • Rotate Logs: Use RotatingFileHandler or TimedRotatingFileHandler to prevent log files from growing indefinitely.
  • Structured Logging: For production, consider using libraries like structlog to output logs in JSON format—this makes it easy to parse logs with tools like Elasticsearch or Splunk.
  • Log Levels: Use appropriate levels (WARNING for transient issues like timeouts, ERROR for critical failures like connection errors) to filter logs effectively.

内容的提问来源于stack exchange,提问作者Subhayan Bhattacharya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:16:01