Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
El SDK de Azure para Python abstrae las llamadas al protocolo de comunicación del servicio de Azure subyacente, tanto si ese protocolo es HTTP como AMQP (que se usa para los SDK de mensajería como ServiceBus y EventHubs). Por ejemplo, si usa una de las bibliotecas que usa HTTP, el SDK de Azure para Python realiza solicitudes HTTP y recibe respuestas HTTP en segundo plano. El SDK abstrae esta complejidad para que pueda trabajar con objetos intuitivos de Python en lugar de respuestas HTTP sin procesar o cargas JSON.
Comprender los tipos de objetos que recibe de las operaciones del SDK es esencial para escribir aplicaciones eficaces de Azure. En este artículo se explican los tipos de respuesta comunes que se encuentran y cómo se relacionan con la comunicación HTTP subyacente.
Nota:
En este artículo solo se examina el escenario HTTP, no el escenario AMQP.
Objetos de Python deserializados
El SDK de Azure para Python prioriza la productividad del desarrollador devolviendo objetos de Python fuertemente tipados a partir de operaciones de servicio. En lugar de analizar JSON o controlar directamente los códigos de estado HTTP, se trabaja con modelos de recursos que representan recursos de Azure como objetos de Python.
Por ejemplo, al recuperar un blob de Azure Storage, recibirá un BlobProperties objeto con atributos como name, sizey last_modified en lugar de un diccionario JSON sin formato:
from azure.storage.blob import BlobServiceClient
# Connect to storage account
blob_service_client = BlobServiceClient.from_connection_string(connection_string)
container_client = blob_service_client.get_container_client("mycontainer")
# Get blob properties - returns a BlobProperties object
blob_client = container_client.get_blob_client("myblob.txt")
properties = blob_client.get_blob_properties()
# Access properties as Python attributes
print(f"Blob name: {properties.name}")
print(f"Blob size: {properties.size} bytes")
print(f"Last modified: {properties.last_modified}")
Dónde proceden los datos
Comprender el flujo de datos le ayuda a apreciar lo que hace el SDK en segundo plano:
-
El código llama a un método del SDK: Se invoca un método como
get_blob_properties(). - El SDK crea una solicitud HTTP: El SDK compila la solicitud HTTP adecuada con encabezados, autenticación y parámetros de consulta.
- El servicio de Azure responde: El servicio devuelve una respuesta HTTP, normalmente con una carga JSON en el cuerpo de la respuesta.
-
El SDK procesa la respuesta: El SDK:
- Comprueba el código de estado HTTP.
- Analiza el cuerpo de la respuesta (normalmente JSON).
- Valida los datos con los esquemas esperados.
- Asigna los datos a objetos de modelo de Python.
- El código recibe objetos de Python: Trabaja con los objetos deserializados, no con datos HTTP sin procesar.
Esta abstracción le permite centrarse en la lógica de la aplicación en lugar de en los detalles del protocolo HTTP.
Tipos de respuesta comunes
El SDK de Azure para Python usa varios tipos de respuesta estándar en todos los servicios. Comprender estos tipos le ayuda a trabajar de forma eficaz con cualquier servicio de Azure.
Modelos de recursos
La mayoría de las operaciones del SDK devuelven modelos de recursos. Estos objetos de Python representan recursos de Azure. Los modelos son específicos del servicio, pero siguen patrones coherentes:
# Azure Key Vault example
from azure.keyvault.secrets import SecretClient
secret_client = SecretClient(vault_url=vault_url, credential=credential)
secret = secret_client.get_secret("mysecret") # Returns KeyVaultSecret
print(f"Secret name: {secret.name}")
print(f"Secret value: {secret.value}")
print(f"Secret version: {secret.properties.version}")
# Azure Cosmos DB example
from azure.cosmos import CosmosClient
cosmos_client = CosmosClient(url=cosmos_url, credential=credential)
database = cosmos_client.get_database_client("mydatabase")
container = database.get_container_client("mycontainer")
item = container.read_item(item="item-id", partition_key="partition-value") # Returns dict
print(f"Item ID: {item['id']}")
ItemPaged para los resultados de la colección
Cuando el SDK enumera los recursos, devuelve ItemPaged objetos que controlan la paginación de forma transparente:
from azure.storage.blob import BlobServiceClient
from azure.core.paging import ItemPaged
blob_service_client = BlobServiceClient.from_connection_string(connection_string)
container_client = blob_service_client.get_container_client("mycontainer")
# list_blobs returns ItemPaged[BlobProperties]
blobs: ItemPaged[BlobProperties] = container_client.list_blobs()
# Iterate naturally - SDK handles pagination
for blob in blobs:
print(f"Blob: {blob.name}, Size: {blob.size}")
Acceso a la respuesta HTTP sin procesar
Aunque las abstracciones de alto nivel del SDK satisfacen la mayoría de las necesidades, a veces necesita acceso a la respuesta HTTP subyacente. Entre los escenarios habituales se incluyen los siguientes:
- Depuración de solicitudes fallidas.
- Acceso a encabezados de respuesta personalizados.
- Implementación de la lógica de reintento personalizada.
- Trabajar con formatos de respuesta no estándar.
La mayoría de los métodos del SDK aceptan un raw_response_hook parámetro:
from azure.keyvault.secrets import SecretClient
secret_client = SecretClient(vault_url=vault_url, credential=credential)
def inspect_response(response):
# Access the raw HTTP response
print(f"Request URL: {response.http_request.url}")
print(f"Status code: {response.http_response.status_code}")
print(f"Response headers: {dict(response.http_response.headers)}")
# Access custom headers
request_id = response.http_response.headers.get('x-ms-request-id')
print(f"Request ID: {request_id}")
# Must return the response
return response
# Hook is called before deserialization
secret = secret_client.get_secret("mysecret", raw_response_hook=inspect_response)
Paginación e iteradores
Los servicios de Azure suelen devolver grandes colecciones de recursos. El SDK usa ItemPaged para controlar estas colecciones de forma eficaz sin cargar todo en memoria a la vez.
Paginación automática
El SDK captura automáticamente las páginas nuevas a medida que recorre en iteración:
# List all blobs - could be thousands
blobs = container_client.list_blobs()
# SDK fetches pages as needed during iteration
for blob in blobs:
process_blob(blob) # Pages loaded on-demand
Trabajar explícitamente con páginas
También puede trabajar con páginas directamente cuando sea necesario:
blobs = container_client.list_blobs()
# Process by page
for page in blobs.by_page():
print(f"Processing page with {len(list(page))} items")
for blob in page:
process_blob(blob)
Control del tamaño de página
Muchas operaciones de lista aceptan un results_per_page parámetro:
# Fetch 100 items per page instead of the default
blobs = container_client.list_blobs(results_per_page=100)
Algunos métodos para algunos servicios de Azure tienen otros mecanismos para controlar el tamaño de página. Por ejemplo, Azure Key Vault y Azure Search usan top kwarg para limitar los resultados por llamada. Para ver un ejemplo que usa el método Azure Search search() , consulte el código fuente.
Caso especial: operaciones y sondeos de larga duración
Algunas operaciones de Azure no se pueden completar inmediatamente. Algunos ejemplos son:
- Creación o eliminación de máquinas virtuales.
- Implementación de plantillas de Azure Resource Manager.
- Entrenamiento de modelos de aprendizaje automático.
- Copiando blobs grandes.
Estas operaciones devuelven objetos de sondeo que realizan un seguimiento del progreso de la operación.
Trabajar con sondeos
from azure.mgmt.storage import StorageManagementClient
storage_client = StorageManagementClient(credential, subscription_id)
# Start storage account creation
poller = storage_client.storage_accounts.begin_create(
resource_group_name="myresourcegroup",
account_name="mystorageaccount",
parameters=storage_parameters
)
# Option 1: Wait for completion (blocking)
storage_account = poller.result()
# Option 2: Check status periodically
while not poller.done():
print(f"Status: {poller.status()}")
time.sleep(5)
storage_account = poller.result()
Sondeos asincrónicos
Cuando se utilizan patrones async/await, se trabaja con AsyncLROPoller:
from azure.storage.blob.aio import BlobServiceClient
async with BlobServiceClient.from_connection_string(connection_string) as client:
container_client = client.get_container_client("mycontainer")
# Start async copy operation
blob_client = container_client.get_blob_client("large-blob.vhd")
poller = await blob_client.begin_copy_from_url(source_url)
# Wait for async completion
copy_properties = await poller.result()
Ejemplo de sondeo de objetos para operaciones de larga duración: Máquinas virtuales
La implementación de máquinas virtuales es un ejemplo de una operación que tarda tiempo en completarse y se gestiona devolviendo objetos de encuesta (LROPoller para código sincrónico, AsyncLROPoller para código asincrónico):
from azure.mgmt.compute import ComputeManagementClient
from azure.core.polling import LROPoller
compute_client = ComputeManagementClient(credential, subscription_id)
# Start VM creation - returns immediately with a poller
poller: LROPoller = compute_client.virtual_machines.begin_create_or_update(
resource_group_name="myresourcegroup",
vm_name="myvm",
parameters=vm_parameters
)
# Wait for completion and get the result
vm = poller.result() # Blocks until operation completes
print(f"VM {vm.name} provisioned successfully")
Respuesta de acceso a los resultados paginados
Para los resultados paginados, use el by_page() método con raw_response_hook:
def page_response_hook(response):
continuation_token = response.http_response.headers.get('x-ms-continuation')
print(f"Continuation token: {continuation_token}")
return response
blobs = container_client.list_blobs()
for page in blobs.by_page(raw_response_hook=page_response_hook):
for blob in page:
print(blob.name)
procedimientos recomendados
Prefiere abstracciones de alto nivel.
Trabaje con los modelos de recursos del SDK en lugar de las respuestas sin procesar siempre que sea posible.
Evite tener acceso a cualquier método con prefijo con un carácter de subrayado (_). Por convención, esos métodos son privados en Python. No hay garantías sobre problemas como cambios importantes en comparación con las API públicas:
# Preferred: Work with typed objects secret = secret_client.get_secret("mysecret") if secret.properties.enabled: use_secret(secret.value) # Avoid: Manual JSON parsing (unless necessary) ... # AND avoid accessing any objects or methods that start with `_` response = secret_client._client.get(...) # Don't access internal clients data = json.loads(response.text) if data['attributes']['enabled']: use_secret(data['value'])Controle correctamente la paginación. Siempre recorre en iteración los resultados paginados en lugar de convertir en una lista:
# Good: Memory-efficient iteration for blob in container_client.list_blobs(): process_blob(blob) # Avoid: Loading everything into memory all_blobs = list(container_client.list_blobs()) # Could consume excessive memoryUse poller.result() para las operaciones de ejecución prolongada. Use siempre el
result()método para asegurarse de que las operaciones se completen correctamente:# Correct: Wait for operation completion poller = compute_client.virtual_machines.begin_delete( resource_group_name="myresourcegroup", vm_name="myvm" ) poller.result() # Ensures deletion completes print("VM deleted successfully") # Wrong: Assuming immediate completion poller = compute_client.virtual_machines.begin_delete(...) print("VM deleted successfully") # Deletion might still be in progress!Acceda a las respuestas sin procesar solo cuando sea necesario. Utiliza el acceso de respuesta en bruto con moderación y solo para requisitos específicos
# Good use case: Debugging or logging def log_request_id(response): request_id = response.http_response.headers.get('x-ms-request-id') logger.info(f"Operation request ID: {request_id}") return response blob_client.upload_blob(data, raw_response_hook=log_request_id) # Good use case: Custom error handling def check_custom_header(response): if response.http_response.headers.get('x-custom-error'): raise CustomApplicationError("Custom error condition detected") return response