bytearray.resize() cambia directamente la longitud de un búfer mutable de bytes. Resulta útil cuando una aplicación necesita reservar espacio, reducir datos ya procesados, crear registros de tamaño fijo o adaptar paquetes binarios sin construir manualmente otro bytearray. Su uso correcto requiere atención a las vistas de memoria, el relleno con ceros, los tamaños no confiables, el rendimiento y la compatibilidad.
Qué representa bytearray
Un bytearray almacena una secuencia mutable de bytes. A diferencia de bytes, permite modificar elementos y segmentos. Por eso es apropiado para búferes de red, formatos de archivo, parsers incrementales e integración con APIs nativas. Para repasar conceptos relacionados, consulta las guías de Academify sobre tipos de datos, archivos grandes, archivos en Python y módulo os.
Comportamiento básico
Cuando el tamaño solicitado es mayor que la longitud actual, resize() amplía el objeto y rellena la zona nueva con bytes cero. Cuando es menor, elimina los bytes finales. La modificación ocurre sobre el mismo objeto, por lo que todas las referencias observan la nueva longitud.
datos = bytearray(b"ABC")
datos.resize(6)
print(datos) # bytearray(b'ABC\x00\x00\x00')
datos.resize(2)
print(datos) # bytearray(b'AB')El método devuelve None, como otras operaciones mutables de Python.
Ampliar un búfer
El relleno automático con ceros facilita la reserva de espacio, pero esos ceros no son necesariamente datos válidos. En un protocolo o archivo binario pueden tener un significado concreto. Antes de guardar o transmitir el búfer, escribe todos los campos esperados.
cabecera = bytearray(b"PKT")
cabecera.resize(8)
cabecera[3:7] = (1250).to_bytes(4, "big")
cabecera[7] = 1Esta técnica deja explícito el tamaño final y evita concatenaciones sucesivas.
Reducir sin perder datos importantes
Reducir el tamaño descarta definitivamente los bytes situados después del nuevo límite. Verifica que ya hayan sido procesados o copiados. En un parser incremental es habitual consumir un mensaje y conservar solamente el resto.
buffer = bytearray(b"MSG1RESTO")
consumidos = 4
del buffer[:consumidos]La eliminación por segmento ya ajusta la longitud. resize() es más útil cuando se conoce directamente el tamaño objetivo.
Validar tamaños
El tamaño debe ser un entero no negativo. Además, una entrada externa nunca debe controlar una asignación ilimitada. Un archivo o paquete malicioso puede declarar una longitud enorme y agotar la memoria.
MAX_BUFFER = 8 * 1024 * 1024
def resize_seguro(buf: bytearray, tamano: int) -> None:
if not isinstance(tamano, int):
raise TypeError("el tamaño debe ser entero")
if not 0 <= tamano <= MAX_BUFFER:
raise ValueError("tamaño fuera del límite")
buf.resize(tamano)En servidores, combina esta regla con timeouts, cuotas por cliente y límites globales de memoria.
memoryview y búferes exportados
Existe un caso importante cuando un memoryview activo apunta al mismo objeto. Python puede impedir el redimensionamiento mientras el búfer está exportado, porque una reasignación podría invalidar la vista.
datos = bytearray(b"abcdef")
vista = memoryview(datos)
try:
# datos.resize(20) puede fallar aquí
pass
finally:
vista.release()
datos.resize(20)Mantén corta la vida de las vistas y libéralas antes de cambiar la longitud. Esto es esencial con bibliotecas nativas, NumPy y APIs sin copia.
resize, extend y segmentos
extend() añade bytes conocidos. resize() establece una longitud objetivo y rellena con ceros. La asignación por segmentos reemplaza una región y también puede alterar la longitud.
buf = bytearray(b"AB")
buf.extend(b"CD")
buf.resize(8)
buf[4:] = b"1234"Usa extend() si ya tienes el contenido; segmentos para reemplazar posiciones concretas; y resize() cuando el requisito principal es el tamaño final.
Paquetes de red
Un cliente de red puede leer una cabecera con la longitud del payload, validarla, ampliar el búfer y rellenarlo a medida que llegan los fragmentos.
def preparar_paquete(prefijo: bytes, payload_size: int) -> bytearray:
limite = 1_000_000
if not 0 <= payload_size <= limite:
raise ValueError("payload inválido")
paquete = bytearray(prefijo)
paquete.resize(len(prefijo) + payload_size)
return paqueteNo supongas que una sola lectura completa toda la región. Registra cuántos bytes llegaron y trata cierres prematuros.
Registros binarios de ancho fijo
El método ayuda a crear campos de tamaño fijo. Un texto puede codificarse, truncarse cuando sea necesario y rellenarse con ceros.
def campo_fijo(texto: str, tamano: int) -> bytes:
buf = bytearray(texto.encode("utf-8"))
if len(buf) > tamano:
del buf[tamano:]
else:
buf.resize(tamano)
return bytes(buf)Evita cortar un carácter UTF-8 multibyte por la mitad. Define una política por caracteres o valida la decodificación después del corte.
Rendimiento
Redimensionar puede requerir reasignación y copia interna. Evita aumentar y reducir repetidamente en cantidades pequeñas dentro de bucles intensivos. Calcula el tamaño final cuando sea posible o crece por bloques. Mide el caso real con herramientas como timeit.
No asumas que resize() siempre será más rápido que concatenar, usar extend() o realizar una única asignación final.
Compatibilidad entre versiones
El proyecto debe declarar la versión mínima de Python. En intérpretes anteriores, la reducción puede implementarse con eliminación de segmentos y la ampliación con bytes cero.
def resize_compatible(buf: bytearray, tamano: int) -> None:
metodo = getattr(buf, "resize", None)
if metodo is not None:
metodo(tamano)
elif tamano < len(buf):
del buf[tamano:]
else:
buf.extend(b"\x00" * (tamano - len(buf)))Manejo de errores
Distingue una entrada inválida de un fallo de asignación o un conflicto con una vista activa. Capturar todas las excepciones oculta la causa. Atrapa solamente los errores que la aplicación pueda tratar y conserva la excepción original.
def reservar(buf: bytearray, tamano: int) -> None:
try:
resize_seguro(buf, tamano)
except (TypeError, ValueError) as exc:
raise ValueError(f"solicitud inválida: {tamano}") from excPruebas recomendadas
Comprueba ampliación, reducción, tamaño cero, tamaño sin cambios, valores negativos, límite máximo, conservación del prefijo y relleno con ceros. Incluye una prueba con memoryview activa para documentar el comportamiento esperado.
def test_ampliacion():
b = bytearray(b"xy")
b.resize(5)
assert b == bytearray(b"xy\x00\x00\x00")
def test_reduccion():
b = bytearray(b"abcdef")
b.resize(3)
assert b == bytearray(b"abc")Seguridad
Reducir un búfer no equivale a borrar de forma garantizada la memoria física. Los secretos requieren mecanismos específicos. También debes limitar tamaños externos y validar operaciones como longitud de cabecera más longitud de contenido.
Buenas prácticas
Valida antes de asignar, documenta el significado del relleno, libera vistas, evita redimensionamientos repetitivos, prueba los límites y convierte el resultado a bytes cuando deba quedar inmutable. Mantén la descripción del formato binario cerca de sus validaciones.
Conclusión
bytearray.resize() expresa claramente la operación de cambiar la longitud de un búfer mutable. Simplifica paquetes, registros fijos y procesamiento binario si se utiliza con límites y pruebas. Consulta la documentación oficial de bytearray y del protocolo de búfer para detalles autoritativos.







