SDK de Python 2.0: soporte para asyncio y Python 3.12+
La versión 2.0.0 de nuestro SDK de Python, pytransloadit, incorpora
AsyncTransloadit, un cliente asyncio que convive con el cliente síncrono que ya usas.
También eleva la versión mínima de Python a 3.12.
A continuación, mostramos para qué sirve el cliente asíncrono y qué revisar antes de actualizar desde 1.x.
¿Por qué un cliente asíncrono?
El cliente 1.x se comunica con nuestra API mediante Requests, que es bloqueante. En una app FastAPI o aiohttp, cada llamada al cliente bloquea el bucle de eventos. Mientras una solicitud espera a que una Assembly termine, las demás solicitudes de ese worker también esperan, a menos que tú traslades la llamada a un pool de hilos.
AsyncTransloadit envía sus llamadas a la API mediante aiohttp y consulta periódicamente
el estado de la Assembly con asyncio.sleep, por lo que puedes usar
await para esperar una Assembly como cualquier otra operación de E/S.
Esto también facilita ejecutar varias Assemblies a la vez desde un script o un worker en segundo plano.
Procesa archivos simultáneamente
Instala 2.0 con Python 3.12 o una versión posterior:
python -m pip install --upgrade 'pytransloadit>=2,<3'
Este script redimensiona tres fotos en paralelo con
🤖 /image/resize, compartiendo un cliente y una sesión HTTP. Lee
tus credenciales de TRANSLOADIT_KEY y TRANSLOADIT_SECRET:
import asyncio
import os
from transloadit.async_client import AsyncTransloadit
async def resize(client, path):
assembly = client.new_assembly()
thumb = {"use": ":original", "width": 400}
assembly.add_step("thumb", "/image/resize", thumb)
with open(path, "rb") as upload:
assembly.add_file(upload)
response = await assembly.create(wait=True, resumable=False)
if "error" in response.data:
raise RuntimeError(f"{path}: {response.data['error']}")
return response.data["results"]["thumb"][0]["ssl_url"]
async def main():
paths = ["chameleon.jpg", "prinsengracht.jpg", "desert.jpg"]
key = os.environ["TRANSLOADIT_KEY"]
secret = os.environ["TRANSLOADIT_SECRET"]
async with AsyncTransloadit(key, secret) as client:
urls = await asyncio.gather(*(resize(client, p) for p in paths))
print("\n".join(urls))
asyncio.run(main())
Descarga las fotos de ejemplo y ejecuta el script:
for photo in chameleon prinsengracht desert; do
curl -fsSLo "$photo.jpg" \
"https://demos.transloadit.com/inputs/$photo.jpg"
done
python resize_many.py
El script imprime una URL por miniatura. En nuestra máquina, las tres Assemblies (25 MB de fotos) terminaron en unos 3 segundos, frente a unos 8 segundos para el mismo bucle con el cliente síncrono.
wait=True retorna cuando la Assembly termina. Los errores de la API siguen
llegando en la respuesta, por lo que el script comprueba error.
resumable=False envía cada archivo en la solicitud de creación. Para archivos grandes,
mantén su valor predeterminado de True: las subidas reanudables usan el
protocolo tus, que el SDK ejecuta en hilos de trabajo, de modo que el bucle de eventos sigue respondiendo
mientras se suben los archivos.
Úsalo en FastAPI
Instala FastAPI, Uvicorn y el analizador multipart que FastAPI necesita para las subidas:
python -m pip install fastapi uvicorn python-multipart
Crea el cliente una sola vez por app y compártelo entre las solicitudes:
import os
from contextlib import asynccontextmanager
from fastapi import FastAPI, HTTPException, UploadFile
from transloadit.async_client import AsyncTransloadit
@asynccontextmanager
async def lifespan(app: FastAPI):
key = os.environ["TRANSLOADIT_KEY"]
secret = os.environ["TRANSLOADIT_SECRET"]
async with AsyncTransloadit(key, secret) as client:
app.state.transloadit = client
yield
app = FastAPI(lifespan=lifespan)
@app.post("/thumbnails")
async def create_thumbnail(file: UploadFile):
assembly = app.state.transloadit.new_assembly()
thumb = {"use": ":original", "width": 400}
assembly.add_step("thumb", "/image/resize", thumb)
assembly.add_file(file.file)
response = await assembly.create(wait=True, resumable=False)
thumbs = response.data.get("results", {}).get("thumb")
if "error" in response.data or not thumbs:
raise HTTPException(502, "Could not create a thumbnail")
return {"url": thumbs[0]["ssl_url"]}
uvicorn app:app
curl -fsSL -F file=@chameleon.jpg http://127.0.0.1:8000/thumbnails
Enviamos tres subidas a este endpoint al mismo tiempo y un worker de Uvicorn respondió a las tres en
menos de 4 segundos. Esperar el resultado dentro de la solicitud es adecuado para tareas rápidas de
procesamiento de imágenes. Para video y otras tareas de larga duración, crea la Assembly sin
wait=True y pasa un notify_url a
new_assembly(), para que Transloadit
llame a tu app cuando termine el procesamiento.
Qué cubre el cliente asíncrono
AsyncTransloadit ofrece las mismas funciones que el cliente síncrono: crear, recuperar,
listar y cancelar Assemblies, gestionar Templates, recuperar
la facturación mensual y firmar URL de Smart CDN. Usa await con los
métodos que acceden a la red.
new_assembly(), new_template() y get_signed_smart_cdn_url()
siguen siendo síncronos.
Usa el cliente con async with o llama a await client.aclose() cuando
termines. Puedes pasar tu propia sesión de aiohttp con session=. Sin embargo,
las transferencias reanudables no usan esa sesión, por lo que su configuración de proxy y TLS no se
aplica a ellas. Configúrala mediante el entorno de Requests.
Actualiza desde 1.x
Tu código síncrono sigue funcionando: from transloadit import client y sus métodos no cambian
en 2.0. Esto es lo que debes revisar:
- Python 3.12 o una versión posterior. Actualiza primero los intérpretes de desarrollo, CI y
despliegue. Con Python 3.9 a 3.11, pip sigue instalando 1.0.4, la última versión de la serie 1.x.
Fija
pytransloadit<2para indicarlo explícitamente. - Versiones mínimas de las dependencias. 2.0 requiere
requests>=2.33,<3yurllib3>=2.7,<3. Flexibiliza las versiones antiguas fijadas en tus restricciones y regenera el archivo de bloqueo. - Redirecciones. Las redirecciones HTTP se devuelven al código que hace la llamada en lugar de seguirse.
- Validación de entrada. Las URL de servicio no válidas y los IDs de Template vacíos generan
ValueError. - Templates. Cuando combines una opción
templateconadd_step(), pasa el valor detemplatecomo un dict, no como una cadena JSON. - Respuestas. Una respuesta que no sea JSON coloca texto o bytes en
Response.data, y un cuerpo vacío produce una cadena vacía. - Consultas periódicas. Con
wait=True, agotar los reintentos de las consultas de estado sujetas a límites de frecuencia generaAssemblyPollingError. La Assembly puede seguir ejecutándose: usa el atributoassembly_urldel error para volver a consultar su estado o cancelarla. - URL de las Assemblies. Las solicitudes de estado y cancelación solo se envían a URL de Assemblies de confianza, y el cliente predeterminado rechaza otros hosts.
- Smart CDN. Los parámetros booleanos se firman como
trueyfalse, de acuerdo con nuestra implementación de referencia en Node.js. Los slugs de Workspace deben ser válidos para DNS, yauth_key,expysigson claves de consulta reservadas.
El README y el registro de cambios de 2.0.0 contienen todas las notas de actualización.
Empieza
python -m pip install --upgrade 'pytransloadit>=2,<3'
Encuentra el paquete en PyPI, scripts síncronos y asíncronos que puedes ejecutar en la carpeta de ejemplos y la referencia de la API en Read the Docs. Nuestra documentación del SDK de Python cubre los conceptos básicos. ¿Aún no tienes cuenta? Regístrate gratis y podrás ejecutar los ejemplos anteriores en unos minutos. En el plan de suscripción gratuito Community, los resultados de imágenes tienen marcas de agua; nuestras preguntas frecuentes explican por qué. Dirige las preguntas o los problemas con la actualización al gestor de incidencias de python-sdk.
