Fouten verwerken die zijn geproduceerd door de Azure SDK voor Python

Het bouwen van betrouwbare cloudtoepassingen vereist meer dan alleen het implementeren van functies. Het vereist ook robuuste strategieën voor foutafhandeling. Wanneer u met gedistribueerde systemen en cloudservices werkt, moet uw toepassing zijn voorbereid om foutscenario's correct af te handelen.

De Azure SDK voor Python biedt een uitgebreid foutmodel dat is ontworpen om ontwikkelaars te helpen tolerante toepassingen te bouwen. Inzicht in dit foutmodel is van cruciaal belang voor:

  • Het verbeteren van de betrouwbaarheid van toepassingen door algemene foutscenario's te anticiperen en te verwerken.
  • Het verbeteren van de gebruikerservaring door zinvolle foutmeldingen en gracieuze degradatie.
  • Vereenvoudig het oplossen van problemen door relevante diagnostische gegevens vast te leggen en te loggen.

In dit artikel wordt de Azure SDK voor de foutarchitectuur van Python verkend en vindt u praktische richtlijnen voor het implementeren van effectieve foutafhandeling in uw toepassingen.

Fouten in Azure SDK voor Python-modellen

De Azure SDK voor Python maakt gebruik van een hiërarchisch uitzonderingsmodel dat algemene en specifieke mogelijkheden voor foutafhandeling biedt. De kern van dit model is AzureError, dat fungeert als de basis-uitzonderingsklasse voor alle fouten met betrekking tot de Azure SDK.

Uitzonderingshiërarchie

AzureError
├── ClientAuthenticationError
├── ResourceNotFoundError
├── ResourceExistsError
├── ResourceModifiedError
├── ResourceNotModifiedError
├── ServiceRequestError
├── ServiceResponseError
└── HttpResponseError

Belangrijke uitzonderingstypen

Fout Description
AzureError De basis-uitzonderingsklasse voor alle Azure SDK-fouten. Gebruik deze uitzondering als catchall wanneer u een Azure-gerelateerde fout moet afhandelen.
ClientAuthenticationError Wordt gegenereerd wanneer de verificatie mislukt. Veelvoorkomende oorzaken zijn ongeldige referenties, verlopen tokens en onjuist geconfigureerde verificatie-instellingen.
ResourceNotFoundError Wordt gegenereerd bij een poging om toegang te krijgen tot een resource die niet bestaat. Deze uitzondering komt meestal overeen met HTTP 404-antwoorden.
ResourceExistsError Wordt gegenereerd bij het maken van een resource die al bestaat. Deze uitzondering helpt bij het voorkomen van onbedoelde overschrijven.
ServiceRequestError Wordt gegenereerd wanneer de SDK geen aanvraag naar de service kan verzenden. Veelvoorkomende oorzaken zijn problemen met de netwerkverbinding, fouten bij het oplossen van domain name system en ongeldige service-eindpunten.
ServiceResponseError Gegenereerd wanneer de service een onverwacht antwoord retourneert dat de SDK niet kan verwerken.
HttpResponseError Gegenereerd voor HTTP-foutreacties (4xx- en 5xx-statuscodes). Deze uitzondering biedt toegang tot de onderliggende HTTP-antwoorddetails.

Veelvoorkomende foutscenario's

Inzicht in typische foutscenario's helpt u bij het implementeren van geschikte afhandelingsstrategieën voor elke situatie.

Verificatie- en autorisatiefouten

Verificatiefouten treden op wanneer de SDK uw identiteit niet kan verifiëren:

from azure.core.exceptions import ClientAuthenticationError
from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient

try:
    credential = DefaultAzureCredential()
    blob_service = BlobServiceClient(
        account_url="https://myaccount.blob.core.windows.net",
        credential=credential
    )
    # Attempt to list containers
    containers = blob_service.list_containers()
except ClientAuthenticationError as e:
    print(f"Authentication failed: {e.message}")
    # Don't retry - fix credentials first

Autorisatiefouten (meestal HttpResponseError met 403 status) treden op wanneer u geen machtigingen hebt:

from azure.core.exceptions import HttpResponseError

try:
    blob_client.upload_blob(data)
except HttpResponseError as e:
    if e.status_code == 403:
        print("Access denied. Check your permissions.")
    else:
        raise

Resourcefouten

Ontbrekende resources probleemloos verwerken:

from azure.core.exceptions import ResourceNotFoundError

try:
    blob_client = container_client.get_blob_client("myblob.txt")
    content = blob_client.download_blob().readall()
except ResourceNotFoundError:
    print("Blob not found. Using default content.")
    content = b"default"

Dubbele resource maken voorkomen:

from azure.core.exceptions import ResourceExistsError

try:
    container_client.create_container()
except ResourceExistsError:
    print("Container already exists.")
    # Continue with existing container

Serverfouten

Afhandelen van fouten aan de serverzijde op de juiste manier:

from azure.core.exceptions import HttpResponseError

try:
    result = client.process_data(large_dataset)
except HttpResponseError as e:
    if 500 <= e.status_code < 600:
        print(f"Server error ({e.status_code}). The service may be temporarily unavailable.")
        # Consider retry logic here
    else:
        raise

Aanbevolen procedures voor foutafhandeling

  • Specifieke afhandeling van uitzonderingen gebruiken: Neem altijd specifieke uitzonderingen op voordat u terugvalt op algemene uitzonderingen:

    from azure.core.exceptions import (
        AzureError,
        ClientAuthenticationError,
        ResourceNotFoundError,
        HttpResponseError
    )
    
    try:
        # Azure SDK operation
        result = client.get_resource()
    except ClientAuthenticationError:
        # Handle authentication issues
        print("Please check your credentials")
    except ResourceNotFoundError:
        # Handle missing resources
        print("Resource not found")
    except HttpResponseError as e:
        # Handle specific HTTP errors
        if e.status_code == 429:
            print("Rate limited. Please retry later.")
        else:
            print(f"HTTP error {e.status_code}: {e.message}")
    except AzureError as e:
        # Catch-all for other Azure errors
        print(f"Azure operation failed: {e}")
    
  • Implementeer de juiste strategieën voor opnieuw proberen: Sommige fouten rechtvaardigen nieuwe pogingen, terwijl andere niet.

    Probeer het niet opnieuw op:

    • 401 Niet geautoriseerd (verificatiefouten)
    • 403 Verboden (autorisatiefouten)
    • 400 Ongeldige aanvraag (clientfouten)
    • 404 Niet gevonden (tenzij u verwacht dat de resource wordt weergegeven)

    Overweeg het opnieuw te proberen op:

    • 408 Time-out aanvraag
    • 429 Te veel aanvragen (met de juiste uitstel)
    • 500 Interne serverfout
    • 502 Ongeldige gateway
    • 503-service niet beschikbaar
    • Time-out van 504 gateway
  • Zinvolle foutinformatie extraheren

    from azure.core.exceptions import HttpResponseError
    
    try:
        client.perform_operation()
    except HttpResponseError as e:
        # Extract detailed error information
        print(f"Status code: {e.status_code}")
        print(f"Error message: {e.message}")
        print(f"Error code: {e.error.code if e.error else 'N/A'}")
    
        # Request ID is crucial for Azure support
        if hasattr(e, 'response') and e.response:
            request_id = e.response.headers.get('x-ms-request-id')
            print(f"Request ID: {request_id}")
    

Beleid en tolerantie opnieuw proberen

De Azure SDK bevat ingebouwde mechanismen voor opnieuw proberen waarmee tijdelijke fouten automatisch worden verwerkt.

Standaardgedrag voor opnieuw proberen

De meeste Azure SDK-clients bevatten standaardbeleid voor opnieuw proberen dat:

  • Probeer het opnieuw bij verbindingsfouten en specifieke HTTP-statuscodes.
  • Gebruik exponentieel uitstel met jitter.
  • Beperk het aantal nieuwe pogingen.

Beleid voor opnieuw proberen aanpassen

Als het standaardgedrag niet bij uw gebruiksscenario past, kunt u het beleid voor opnieuw proberen aanpassen:

from azure.storage.blob import BlobServiceClient
from azure.core.pipeline.policies import RetryPolicy

# Create a custom retry policy
retry_policy = RetryPolicy(
    retry_total=5,  # Maximum retry attempts
    retry_backoff_factor=2,  # Exponential backoff factor
    retry_backoff_max=60,  # Maximum backoff time in seconds
    retry_on_status_codes=[408, 429, 500, 502, 503, 504]
)

# Apply to client
blob_service = BlobServiceClient(
    account_url="https://myaccount.blob.core.windows.net",
    credential=credential,
    retry_policy=retry_policy
)

Voorkom het afhandelen van netwerk- en time-outfouten met aangepaste lussen

Probeer ingebouwde herhalingen te gebruiken voor netwerkfouten en time-out fouten voordat u uw eigen aangepaste logica implementeert.

from azure.core.exceptions import ServiceRequestError
import time

# Avoid this approach if possible
max_retries = 3
retry_count = 0

while retry_count < max_retries:
    try:
        response = client.get_secret("mysecret")
        break
    except ServiceRequestError as e:
        retry_count += 1
        if retry_count >= max_retries:
            raise
        print(f"Network error. Retrying... ({retry_count}/{max_retries})")
        time.sleep(2 ** retry_count)  # Exponential backoff

Circuitonderbrekerpatronen implementeren

Voor kritieke bewerkingen kunt u overwegen om circuitonderbrekerpatronen te implementeren:

class CircuitBreaker:
    def __init__(self, failure_threshold=5, recovery_timeout=60):
        self.failure_threshold = failure_threshold
        self.recovery_timeout = recovery_timeout
        self.failure_count = 0
        self.last_failure_time = None
        self.state = 'closed'  # closed, open, half-open
    
    def call(self, func, *args, **kwargs):
        if self.state == 'open':
            if time.time() - self.last_failure_time > self.recovery_timeout:
                self.state = 'half-open'
            else:
                raise Exception("Circuit breaker is open")
        
        try:
            result = func(*args, **kwargs)
            if self.state == 'half-open':
                self.state = 'closed'
                self.failure_count = 0
            return result
        except Exception as e:
            self.failure_count += 1
            self.last_failure_time = time.time()
            
            if self.failure_count >= self.failure_threshold:
                self.state = 'open'
            
            raise e

Foutberichten en codes begrijpen

Azure-services retourneren gestructureerde foutreacties die waardevolle foutopsporingsgegevens bieden.

  • Foutantwoorden parseren

    from azure.core.exceptions import HttpResponseError
    import json
    
    try:
        client.create_resource(resource_data)
    except HttpResponseError as e:
        # Many Azure services return JSON error details
        if e.response and e.response.text():
            try:
                error_detail = json.loads(e.response.text())
                print(f"Error code: {error_detail.get('error', {}).get('code')}")
                print(f"Error message: {error_detail.get('error', {}).get('message')}")
    
                # Some services provide additional details
                if 'details' in error_detail.get('error', {}):
                    for detail in error_detail['error']['details']:
                        print(f"  - {detail.get('code')}: {detail.get('message')}")
            except json.JSONDecodeError:
                print(f"Raw error: {e.response.text()}")
    
  • Diagnostische gegevens vastleggen: Leg altijd diagnostische gegevens vast voor het oplossen van problemen:

    import logging
    from azure.core.exceptions import AzureError
    
    logger = logging.getLogger(__name__)
    
    try:
        result = client.perform_operation()
    except AzureError as e:
        # Log comprehensive error information
        logger.error(
            "Azure operation failed",
            extra={
                'error_type': type(e).__name__,
                'error_message': str(e),
                'operation': 'perform_operation',
                'timestamp': datetime.utcnow().isoformat(),
                'request_id': getattr(e.response, 'headers', {}).get('x-ms-request-id') if hasattr(e, 'response') else None
            }
        )
        raise
    
  • Logboekregistratie en diagnostische gegevens: Logboekregistratie op SDK-niveau inschakelen voor gedetailleerde probleemoplossing:

    import logging
    import sys
    
    # Configure logging for Azure SDKs
    logging.basicConfig(level=logging.DEBUG)
    
    # Enable HTTP request/response logging
    logging.getLogger('azure.core.pipeline.policies.http_logging_policy').setLevel(logging.DEBUG)
    
    # For specific services
    logging.getLogger('azure.storage.blob').setLevel(logging.DEBUG)
    logging.getLogger('azure.identity').setLevel(logging.DEBUG)
    

    Zie Logboekregistratie configureren in de Azure-bibliotheken voor Python voor meer informatie over logboekregistratie.

  • Netwerktracering gebruiken: Schakel tracering op netwerkniveau in voor uitgebreide foutopsporing:

    Belangrijk

    HTTP-logboekregistratie kan gevoelige informatie bevatten, zoals accountsleutels in headers en andere referenties. Zorg ervoor dat u deze logboeken beveiligt om beveiliging te voorkomen.

    from azure.storage.blob import BlobServiceClient
    
    # Enable network tracing
    blob_service = BlobServiceClient(
        account_url="https://myaccount.blob.core.windows.net",
        credential=credential,
        logging_enable=True,  # Enable logging
        logging_body=True     # Log request/response bodies (careful with sensitive data)
    )
    

Speciale overwegingen voor asynchrone programmering

Wanneer u asynchrone clients gebruikt, is voor foutafhandeling speciale aandacht vereist.

  • Eenvoudige asynchrone foutafhandeling

    import asyncio
    from azure.core.exceptions import AzureError
    
    async def get_secret_async(client, secret_name):
        try:
            secret = await client.get_secret(secret_name)
            return secret.value
        except ResourceNotFoundError:
            print(f"Secret '{secret_name}' not found")
            return None
        except AzureError as e:
            print(f"Error retrieving secret: {e}")
            raise
    
  • Annuleringen afhandelen

    async def long_running_operation(client):
        try:
            result = await client.start_long_operation()
            # Wait for completion
            final_result = await result.result()
            return final_result
        except asyncio.CancelledError:
            print("Operation cancelled")
            # Cleanup if necessary
            if hasattr(result, 'cancel'):
                await result.cancel()
            raise
        except AzureError as e:
            print(f"Operation failed: {e}")
            raise
    
  • Gelijktijdige foutafhandeling

    async def process_multiple_resources(client, resource_ids):
        tasks = []
        for resource_id in resource_ids:
            task = client.get_resource(resource_id)
            tasks.append(task)
    
        results = []
        errors = []
    
        # Use gather with return_exceptions to handle partial failures
        outcomes = await asyncio.gather(*tasks, return_exceptions=True)
    
        for resource_id, outcome in zip(resource_ids, outcomes):
            if isinstance(outcome, Exception):
                errors.append((resource_id, outcome))
            else:
                results.append(outcome)
    
        # Process successful results and errors appropriately
        if errors:
            print(f"Failed to process {len(errors)} resources")
            for resource_id, error in errors:
                print(f"  - {resource_id}: {error}")
    
        return results
    

Samenvatting van aanbevolen procedures

Voor effectieve foutafhandeling in Azure SDK voor Python-toepassingen moet u het volgende doen:

  • Verwachte fouten: Cloudtoepassingen moeten probleemloos gedeeltelijke fouten verwachten en afhandelen.
  • Specifieke afhandeling van uitzonderingen gebruiken: Ondervang specifieke uitzonderingen, zoals ResourceNotFoundError en ClientAuthenticationError voordat u terugvalt op algemene AzureError verwerking.
  • Slimme logica voor opnieuw proberen implementeren: Gebruik ingebouwd beleid voor opnieuw proberen of pas deze aan op basis van uw behoeften. Houd er rekening mee dat niet alle fouten nieuwe pogingen moeten activeren.
  • Diagnostische gegevens vastleggen: Registreer altijd aanvraag-id's, foutcodes en tijdstempels voor effectieve probleemoplossing.
  • Geef zinvolle gebruikersfeedback op: Transformeer technische fouten in gebruiksvriendelijke berichten terwijl u technische details voor ondersteuning behoudt.
  • Testsituaties met fouten: Neem foutafhandeling op in uw testdekking om ervoor te zorgen dat uw toepassing zich correct gedraagt onder foutsituaties.