Skip to main content

Fast binary serializer for Python with optional C acceleration.

Project description

🥒 compickle

Serialización binaria para Python con motor en C — rápido, compacto y sin dependencias.

Python Lenguaje C Licencia Compilación


¿Qué es compickle?

compickle es un serializador binario escrito principalmente en C y expuesto como extensión nativa de Python. Está diseñado para ser muy simple de usar y más rápido que el módulo estándar pickle en la mayoría de cargas de trabajo, gracias a:

  • Un buffer de salida dinámico que crece en potencias de 2.
  • Una tabla de deduplicación con hashing FNV-1a O(1) amortizado (capacidad de hasta 8 192 entradas).
  • Compilación nativa con -O3 -march=native -mtune=native.
  • Un fallback puro en Python que se activa automáticamente si la extensión C no está disponible.

⚙️ Instalación

pip install .

O para desarrollo (compilación en el directorio actual):

python setup.py build_ext --inplace

El compilador usa -O3 -march=native -mtune=native automáticamente, generando código optimizado para tu arquitectura específica.


🚀 Uso rápido

import compickle

# Serializar cualquier objeto a archivo
datos = {
    "nombre": "Rex",
    "edad": 5,
    "activo": True,
    "coordenadas": (4.0, 2.0),
    "etiquetas": {"perro", "mascota"},
}

compickle.dump(datos, "datos.cpkl")

# Deserializar desde archivo
copia = compickle.load("datos.cpkl")

# Verificar qué motor está activo
print(compickle.backend())  # → 'c' o 'python'

📖 API completa

compickle.dump(obj, path)

Serializa obj y escribe el resultado binario en path.

compickle.dump(mi_objeto, "salida.cpkl")
  • Usa el motor C si está disponible; Python puro en caso contrario.
  • Resetea automáticamente la tabla de deduplicación antes de cada serialización.

compickle.load(path)

Lee el archivo binario en path y reconstruye el objeto original.

obj = compickle.load("salida.cpkl")

compickle.dedup_reset()

Resetea manualmente la tabla interna de deduplicación (tanto la del motor C como la del fallback Python).

compickle.dedup_reset()

Útil si reutilizas el proceso para serializar muchos objetos distintos en sesiones largas.


compickle.backend()

Devuelve el motor activo.

compickle.backend()  # → 'c'  (extensión compilada)
                     # → 'python'  (fallback puro Python)

🧩 Tipos soportados

Tipo Python Deduplicado Notas
None 1 byte: 0x00
bool 1 byte: 0x80 / 0x81
int Enteros 0–59 en 1 byte; arbitrario big-endian
float IEEE 754 doble precisión (8 bytes)
complex Dos float64 big-endian (16 bytes)
str UTF-8 + FNV-1a hash
bytes Deduplicado por contenido
bytearray Deduplicado por contenido
list Elementos serializados recursivamente
tuple Elementos serializados recursivamente
set Ordenado por repr() para reproducibilidad
frozenset Ordenado por repr() para reproducibilidad
dict Claves y valores serializados recursivamente
function Nombre + código fuente (via inspect.getsource)
closure Fuente + variables capturadas del closure
class (tipo) Nombre + módulo + código fuente
Instancia (__dict__) Clase + fuente + estado del __dict__
Instancia (__slots__) Recorre MRO completo para capturar todos los slots
Objeto con __reduce__ Prioridad máxima; soporta estado opcional

🔬 Cómo funciona internamente

Motor C (compickle.c)

El corazón de compickle es una extensión CPython que implementa:

Buffer dinámico (Buf)

buf_grow → realloc en potencias de 2 (inicio: 8 192 bytes)
buf_u8  → escribe 1 byte
buf_raw → escribe N bytes con memcpy

Tabla de deduplicación (FNV-1a)

Capacidad: 8 192 entradas (DEDUP_CAP)
Buckets:   16 384 (HASH_BUCKETS)
Colisiones: lista enlazada (campo .next)

Cuando un bloque de bytes se ha visto antes, se emite una referencia compacta (2–5 bytes) en lugar de repetir los datos. Los strings largos, bloques de código fuente y datos binarios se benefician enormemente de esto.

Codificación de longitudes (variable)

n ≤ 0x3F      → 1 byte
n ≤ 0x3FFF    → 2 bytes (bit 0x40 marcador)
n > 0x3FFF    → 5 bytes (0xFF + uint32 big-endian)

Prioridad de serialización de objetos

1. __reduce__ explícito en la clase  →  tag 0x1F
2. __dict__ disponible               →  tag 0x1C
3. __slots__ sin __dict__            →  tag 0x1E (recorre MRO completo)

Fallback Python (compickle.py)

Si la extensión C no compila, compickle.py implementa exactamente el mismo protocolo binario en Python puro, con las mismas tags y el mismo esquema de deduplicación. El API público es idéntico; solo cambia la velocidad.


Carga diferida (__init__.py)

El módulo público usa lazy loading: la extensión C solo se importa en la primera llamada a dump, load, dedup_reset o backend(). Esto evita errores en import si la extensión no está compilada todavía.

compickle.backend()  # ← importa la extensión C aquí, la primera vez

🏗️ Estructura del proyecto

compickle/
├── compickle.c        # Motor principal en C (extensión CPython)
├── compickle.py       # Implementación de referencia en Python puro
├── __init__.py        # API pública con lazy loading
└── setup.py           # Build con -O3 -march=native -mtune=native

🧪 Ejemplo avanzado: clases, slots y reduce

import compickle

# ── Clase con __dict__ ──────────────────────────────────────────────
class Punto:
    def __init__(self, x, y):
        self.x = x
        self.y = y

p = Punto(3.0, 7.5)
compickle.dump(p, "punto.cpkl")
p2 = compickle.load("punto.cpkl")
print(p2.x, p2.y)  # → 3.0  7.5

# ── Clase con __slots__ ─────────────────────────────────────────────
class Vector:
    __slots__ = ("x", "y", "z")
    def __init__(self, x, y, z):
        self.x, self.y, self.z = x, y, z

v = Vector(1, 2, 3)
compickle.dump(v, "vector.cpkl")
v2 = compickle.load("vector.cpkl")
print(v2.x, v2.y, v2.z)  # → 1  2  3

# ── Objeto con __reduce__ ───────────────────────────────────────────
class Color:
    def __init__(self, r, g, b):
        self.r, self.g, self.b = r, g, b

    def __reduce__(self):
        return (Color, (self.r, self.g, self.b))

c = Color(255, 128, 0)
compickle.dump(c, "color.cpkl")
c2 = compickle.load("color.cpkl")
print(c2.r, c2.g, c2.b)  # → 255  128  0

📦 Formato binario (resumen de tags)

0x00        None
0x02        int (arbitrario)
0x03        float (8 bytes)
0x04        complex (16 bytes)
0x05        str (UTF-8, deduplicado)
0x06        bytes (deduplicado)
0x07        bytearray (deduplicado)
0x08        list
0x09        tuple
0x0A        set
0x0B        frozenset
0x0C        dict
0x0D        function (nombre + fuente)
0x12        class (nombre + módulo + fuente)
0x1C        instancia con __dict__
0x1E        instancia con __slots__
0x1F        instancia vía __reduce__
0x80/0x81   False / True
0xC0–0xFB   int pequeño (0–59, 1 byte)
0xFB        bloque nuevo para dedup
0xFC–0xFE   referencia dedup (4 / 2 / 1 byte de índice)

📄 Licencia

MIT — úsalo como quieras.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

compickle-1.0.2.tar.gz (18.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

compickle-1.0.2-cp313-cp313-android_24_arm64_v8a.whl (51.6 kB view details)

Uploaded Android API level 24+ ARM64 v8aCPython 3.13

File details

Details for the file compickle-1.0.2.tar.gz.

File metadata

  • Download URL: compickle-1.0.2.tar.gz
  • Upload date:
  • Size: 18.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-requests/2.33.1

File hashes

Hashes for compickle-1.0.2.tar.gz
Algorithm Hash digest
SHA256 28d296aa4350d41bc28a8f76f31cf88ba2bd20c06dcec2ac6c64bea13d0f18ee
MD5 32e9442e5dd98c41aeaaa0b7c9d17b1b
BLAKE2b-256 ec459e2c7923b84d1b46e6fcd9495a722ea1ded8f1fc28bc5a7cf6779a17ed8d

See more details on using hashes here.

File details

Details for the file compickle-1.0.2-cp313-cp313-android_24_arm64_v8a.whl.

File metadata

File hashes

Hashes for compickle-1.0.2-cp313-cp313-android_24_arm64_v8a.whl
Algorithm Hash digest
SHA256 6c1cf01713b55cb22833b8b52f1a2100d0970e1f74e3f653f5e353f7ff5d0ace
MD5 01003fef6da1e123d8cfd453ccb45fcb
BLAKE2b-256 acea64b9f0e85c17136e30afa98e64fcf808fd3352e923184818f01b0eecd8ce

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page