Un AttributeError de Python que muestra "'bytes' object has no attribute 'encode'" al llamar a ZRC.post() significa que el SDK intentó llamar a .encode('utf-8') en un cuerpo que ya eran bytes. El código del conector asume que el cuerpo es una cadena de texto y la doble codificación de bytes causa el fallo[1].
Qué significa
ZRC.post() en el conector de Zoho CRM para Python prepara el cuerpo de la solicitud llamando a data.encode('utf-8') antes de enviarlo. Si pasas un cuerpo que ya es un objeto bytes (por ejemplo, una carga útil FormData/bytes o algo previamente codificado), el código genera un AttributeError porque los objetos bytes no tienen un método encode. Esto es una discrepancia del lado del cliente entre la expectativa del SDK y el tipo que proporcionaste[1][2].
Causas comunes
- Pasar un objeto
bytes(binario) aZRC.post()en lugar de unastrde Python[1]. - Construir una carga útil
multipart/FormDatao usar un ayudante que devuelvebytes, y luego pasar eso directamente aZRC.post()[1]. - Doble codificación: llamas a
urlencodeo codificas abytesde otra manera, y luego el SDK intenta codificar de nuevo[1]. - Usar una versión del SDK que siempre llama a
data.encode(...)sin verificar si sonbytes(error del conector)[1].
Cómo solucionarlo
- Prefiere enviar una cadena de texto. Si tienes bytes, decodifica a texto primero:
- body = body_bytes.decode('utf-8')
- llama a ZRC.post(endpoint, body, config)
- Para POSTs codificados en formulario, usa
urllib.parse.urlencode(...)que devuelve unastr, y luego establece la cabeceraContent-Type:
- from urllib.parse import urlencode
- payload = urlencode(params)
- config['headers'] = {'Content-Type': 'application/x-www-form-urlencoded'}
- ZRC.post(endpoint, payload, config)
- Si debes enviar
multipart/form-databinario (archivos), llama directamente al cliente HTTP en lugar deZRC.post(), o adapta el conector para que admitabytes. Usarequestscon la misma autenticación/token recuperado de tu conexión de Zoho. - Solución temporal (workaround local) en
zcconnector/_init_.py: cambia la línea que codifica los datos para que solo codifique cuandodatasea unastr. Ejemplo de reemplazo:
- if isinstance(data, bytes): body = data
- elif data is not None: body = data.encode('utf-8')
- else: body = None
Aplica esta solución solo en entornos que controles; incluye la traza de pila original y las líneas de código al informar.
- Si crees que el conector debería aceptar
bytespor defecto, abre un informe de error en la comunidad de Zoho con un ejemplo mínimo reproducible (endpoint, tipo de carga útil, traza de pila) para que el SDK pueda ser corregido upstream[1].
Cuándo escalar
Abre un ticket de soporte o presenta un error si no puedes cambiar el tipo del cuerpo (por ejemplo, una biblioteca de terceros siempre devuelve bytes), o si necesitas soporte para carga de archivos multipart dentro de ZRC.post(). Incluye la traza de pila exacta, la versión del SDK y un fragmento reproducible corto para que el equipo de ingeniería pueda parchear el conector[1].
[1]: Error de codificación del cuerpo ZRC.post() de la función CRM Python (hilo de la comunidad de Zoho).
[2]: Listado de la comunidad de Zoho sobre el mismo tema.