Mejores prácticas del SDK de Python
Una lista de verificación probada en producción para usar bien el SDK de Python anthropic: configuración del cliente, elección síncrona/asíncrona, reintentos, streaming y manejo de errores.
Cómo usar esta lista de verificación
- Trata cada elemento como una regla positiva: lo que se debe hacer, no solo un error a evitar.
- Revísala una vez al poner en marcha un nuevo servicio que llama a Claude, y luego vuelve a la sección D cada vez que añadas un nuevo modo de fallo en producción.
- Empareja esto con las páginas dedicadas enlazadas en "Relacionados" para obtener la explicación completa detrás de cualquier regla individual.
A - Configuración del cliente
- Construye el cliente una vez y reutilízalo. Crea
Anthropic()oAsyncAnthropic()al inicio del módulo o de la aplicación, no dentro de un manejador de solicitudes o cuerpo de bucle; reconstruirlo por llamada descarta la agrupación de conexiones. - Lee la clave de API del entorno por defecto. Deja que
Anthropic()recojaANTHROPIC_API_KEYautomáticamente en lugar de codificar una cadena de clave en el código fuente; pasaapi_key=...explícitamente solo cuando la clave provenga de un gestor de secretos en tiempo de ejecución. - Fija la versión del SDK en tu archivo de dependencias. Una dependencia
anthropicsin fijar puede introducir nuevos campos de respuesta o tipos de bloque entre despliegues; fíjala y actualízala deliberadamente. - Establece
max_retriesytimeoutdeliberadamente, no por accidente. Decide los valores basándote en si la llamada es interactiva (timeout corto, pocos reintentos) o un trabajo en segundo plano (timeout más amplio, más reintentos), en lugar de dejar cada sitio de llamada con los mismos valores predeterminados. - Solo recurre a un
http_clientpersonalizado cuando tengas un requisito de infraestructura real. Proxies, paquetes de CA personalizados y ajuste de la agrupación de conexiones son razones válidas; no añadas complejidad de forma especulativa.
B - Síncrono vs Asíncrono
- Adapta el cliente al modelo de concurrencia de tu programa, no al revés. Usa
Anthropic()en scripts, CLIs y frameworks síncronos; usaAsyncAnthropic()en servicios web asíncronos y en cualquier lugar donde crees llamadas concurrentes. - Nunca llames al cliente síncrono directamente dentro de una ruta
async def. Bloquea todo el bucle de eventos durante la duración de la llamada; usaAsyncAnthropic()en manejadores asíncronos, o envuelve llamadas síncronas inevitables en un pool de hilos. - Usa
asyncio.gatherpara obtener realmente concurrencia del cliente asíncrono. Esperar cada llamada secuencialmente dentro de un bucle renuncia al beneficio de rendimiento que motivó la elección deAsyncAnthropic()en primer lugar. - Limita la creación concurrente ilimitada con un semáforo.
asyncio.gatherilimitado sobre muchas solicitudes puede abrumar tus propios límites de tasa; limítalo a un número de concurrencia sensato para la carga de trabajo. - No cambies a asíncrono solo por razones de latencia. Una sola solicitud tarda el mismo tiempo de reloj de pared en ambos clientes; asíncrono solo vale la pena cuando múltiples solicitudes se superponen.
C - Streaming
- Haz streaming de cualquier solicitud donde
max_tokenssea grande. Por encima de aproximadamente 16.000 tokens de salida, una llamada no streaming corre el riesgo de un timeout HTTP del lado del cliente;client.messages.stream()evita ese riesgo independientemente del tamaño de la salida. - Usa
text_streampara el caso común, eventos crudos solo cuando los necesites.text_streammaneja el análisis de texto plano; recurre a la iteración de eventos crudos solo cuando necesites eventos de uso de herramientas o de pensamiento en medio del stream. - Llama a
get_final_message()después del bucle, no antes. Devuelve el mismoMessagecompleto y tipado que devolvería una llamada no streaming, incluyendostop_reasonyusage; no reconstruyas esa información manualmente a partir de fragmentos acumulados. - Empareja
with/async withcon el cliente que estés usando. El streaming deAnthropic()usawithyfor; el streaming deAsyncAnthropic()usaasync withyasync for. Mezclarlos genera unTypeError. - Envuelve las llamadas de streaming en el mismo manejo de errores que las no streaming. Una conexión caída se manifiesta como una excepción desde dentro de la iteración, no antes de que comience; no asumas que las llamadas de streaming están exentas de los patrones de reintento/excepción que usas en otros lugares.
D - Manejo de errores
- Captura excepciones tipadas, las más específicas primero. Encadena
except anthropic.NotFoundError,except anthropic.RateLimitError,except anthropic.APIStatusError,except anthropic.APIConnectionErroren lugar de unexcept Exceptionamplio. - No crees lógica de reintento personalizada para lo que el SDK ya reintenta. Los errores de red,
429,5xx,408y409se reintentan automáticamente hastamax_retries; añade tu propio manejo para lo que sucede después de que se agoten los reintentos, no para duplicarlos. - Nunca reintentes un
400,401,403,404o422sin cambios. Estos no se pueden reintentar por diseño: la solicitud en sí necesita cambiar, no solo reenviarse. - Registra
e.status_code,e.messageye.typeenAPIStatusError, no la cadena de excepción cruda. El campo.typeproporciona una clasificación más detallada que solo el estado HTTP (distinguiendorate_limit_errordeoverloaded_error, por ejemplo). - Falla rápido en
AuthenticationError. Una clave de API incorrecta o faltante no se resuelve por sí sola al reintentar; manifiéstate ruidosamente en lugar de entrar en un bucle. - Tipifica tus propias funciones contra
MessageyContentBlock, nodictoAny. Esto es lo que permite a un verificador de tipos detectar un sitio de llamada mal formado antes de ejecutar el código, y lo que hace que el estrechamientoisinstance()en bloques de contenido sea realmente útil.
Preguntas frecuentes
¿Es seguro omitir la configuración de reintentos y usar los valores predeterminados del SDK?
Generalmente, sí.
Los valores predeterminados (max_retries=2, timeout=600.0 segundos) son valores razonables de propósito general; solo anúlalos cuando un escenario específico (interfaz de usuario interactiva, trabajo por lotes en segundo plano) requiera algo más estricto o más amplio.
¿Qué elemento de esta lista es más importante para un nuevo servicio de producción?
Construir el cliente una vez al inicio (elemento A1) y elegir síncrono vs asíncrono para que coincida con el modelo de concurrencia real de tu programa (elemento B1): ambos son fundamentales, y equivocarse en cualquiera de ellos se agrava en todos los demás elementos de esta lista.
¿Necesito seguir las reglas de streaming si mis respuestas son siempre cortas?
No estrictamente; es poco probable que una respuesta corta y limitada alcance un timeout del lado del cliente sin streaming. El streaming se vuelve importante a medida que max_tokens crece o cuando deseas retroalimentación incremental de la interfaz de usuario.
¿Por qué la sección asíncrona advierte contra llamar al cliente síncrono dentro de `async def`?
Porque bloquea todo el bucle de eventos, no solo la solicitud actual; cada otra solicitud que está siendo atendida por ese mismo proceso asíncrono se detiene durante la duración de la llamada bloqueante, no solo la que la hizo.
¿Es alguna vez aceptable capturar una única excepción amplia?
Para un script genuinamente desechable donde cualquier fallo simplemente significa "detenerse e imprimir un error", una captura amplia está bien. En cualquier código que esté destinado a ejecutarse sin supervisión o a servir tráfico, la cadena específica primero en la sección D vale la pena las líneas adicionales.
¿Cuál es el error más común que cometen los equipos con este SDK?
Esperar llamadas de herramientas o solicitudes asíncronas secuencialmente en un bucle en lugar de usar asyncio.gather; compila, funciona y renuncia silenciosamente a la concurrencia que fue la razón principal para elegir el cliente asíncrono.
¿Debo añadir siempre un `http_client` personalizado para los despliegues de producción?
No.
Añádelo solo cuando haya un requisito concreto (un proxy, un paquete de CA privado, ajuste de la agrupación de conexiones); es un punto de personalización avanzado, no un paso de endurecimiento de producción por defecto.
¿Difieren estas prácticas entre `Anthropic()` y `AsyncAnthropic()`?
Las prácticas subyacentes (manejo de reintentos, disciplina de streaming, respuestas tipadas) son idénticas; solo la sintaxis (await, async with, async for) difiere entre las dos clases de cliente.
¿Con qué frecuencia debo revisar esta lista de verificación?
Cada vez que añadas un nuevo sitio de llamada con requisitos de fiabilidad o latencia diferentes a los tuyos existentes, o después de un incidente de producción que se rastreó hasta la configuración de manejo de errores o timeouts.
¿Es realmente necesario fijar la versión del SDK para un proyecto pequeño?
Tiene menos riesgo para un proyecto pequeño, pero aún así vale la pena hacerlo; una dependencia sin fijar puede introducir un nuevo campo de respuesta o tipo de bloque entre despliegues sin previo aviso, lo que es un error más difícil de rastrear que un cambio de versión que elegiste deliberadamente.
Relacionados
- El modelo mental del SDK de Python de Anthropic - la base conceptual de esta lista de verificación
- Elección entre Anthropic() y AsyncAnthropic() en código de producción - la decisión completa síncrona/asíncrona, ampliada desde la sección B
- Referencia de configuración de reintentos y timeouts del SDK de Python - cada configuración detrás de la regla de reintentos/timeouts de la sección A
- Tipos de excepciones del SDK de Python de un vistazo - la jerarquía completa de excepciones detrás de la sección D
Versiones de la pila: Escrito contra la línea de modelos de Claude actual a partir de ~junio de 2026 - Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5 (el predeterminado), y Claude Haiku 4.5 - y el SDK oficial de Python
anthropic(última versión 0.x). Los nombres de los modelos, las versiones del SDK y los precios cambian rápidamente; verifica los detalles actuales en platform.claude.com/docs antes de confiar en ellos.