Cython: cómo acelerar Python compilando a C

Publicado el: 11/07/2026
Tempo de leitura: 6 minutos
Como converter código Python para C usando Cython

Cython permite escribir código parecido a Python que se traduce a C y se compila como una extensión. Su objetivo principal es mejorar el rendimiento de secciones críticas y facilitar la integración con bibliotecas en C. No convierte automáticamente cualquier programa en una aplicación ultrarrápida: los mejores resultados aparecen cuando se identifican cuellos de botella concretos y se añaden tipos estáticos a operaciones intensivas.

Cuándo considerar Cython

Cython es útil cuando un perfil muestra que gran parte del tiempo se consume en bucles numéricos, acceso repetido a atributos, llamadas de funciones pequeñas o interacción con APIs de C. Antes de compilar, mide el programa con la guía de cProfile en Python. Optimizar una parte que representa el 2% del tiempo total apenas cambiará la aplicación.

Qué genera Cython

Un archivo .pyx se transforma en código C. Después, un compilador crea una extensión que Python puede importar. El flujo general es:

archivo.pyx → código C → extensión compilada → import en Python

La guía oficial de compilación de Cython explica los métodos principales para construir extensiones.

Instalar Cython

Crea un entorno virtual y ejecuta:

python -m pip install cython setuptools

También necesitas un compilador de C compatible con tu plataforma. En Windows suele utilizarse Microsoft C++ Build Tools; en Linux, GCC; y en macOS, las herramientas de línea de comandos de Xcode.

Primer archivo .pyx

Crea calculos.pyx:

def sumar(int a, int b):
    return a + b

Los parámetros tienen tipos C. La función sigue siendo accesible desde Python.

Compilar con setup.py

Una configuración sencilla:

from setuptools import setup
from Cython.Build import cythonize

setup(
    ext_modules=cythonize(
        "calculos.pyx",
        compiler_directives={"language_level": "3"},
    )
)

Compila en el mismo directorio:

python setup.py build_ext --inplace

Después puedes importar:

from calculos import sumar
print(sumar(2, 3))

Usar pyximport durante pruebas

Para experimentar:

import pyximport
pyximport.install(language_level=3)

import calculos

Este método es cómodo en desarrollo, pero un proceso de construcción explícito resulta más reproducible para paquetes y producción.

Python puro frente a tipos C

Compilar código dinámico puede aportar una mejora moderada, pero los mayores beneficios aparecen al declarar variables:

def suma_cuadrados(int limite):
    cdef long total = 0
    cdef int i

    for i in range(limite):
        total += i * i

    return total

cdef crea variables internas de C. Esto reduce creación de objetos Python y comprobaciones en cada iteración.

Funciones cdef, def y cpdef

def crea una función visible desde Python. cdef crea una función interna de C, más rápida de llamar desde código Cython, pero no importable directamente desde Python. cpdef genera una interfaz para ambos mundos.

cdef int interno(int x):
    return x * 2

cpdef int duplicar(int x):
    return interno(x)

No conviertas todas las funciones a cdef. Mantén una interfaz Python clara y mueve solo las operaciones críticas al nivel compilado.

Type hints y modo Python puro

Cython también admite archivos .py con anotaciones y decoradores:

import cython

@cython.ccall
def multiplicar(a: cython.int, b: cython.int) -> cython.int:
    return a * b

Este enfoque mantiene un archivo más parecido a Python normal. Los type hints en Python y los tipos de Cython no tienen exactamente el mismo objetivo: unos ayudan al análisis; los otros pueden cambiar la representación y el rendimiento compilado.

Bucles numéricos

Un caso clásico consiste en recorrer arrays o buffers. Para NumPy, utiliza memoryviews tipadas:

import cython

@cython.boundscheck(False)
@cython.wraparound(False)
def sumar_array(double[:] valores):
    cdef Py_ssize_t i
    cdef double total = 0

    for i in range(valores.shape[0]):
        total += valores[i]

    return total

Desactivar comprobaciones puede mejorar velocidad, pero un índice incorrecto puede provocar errores graves. Hazlo solo cuando las pruebas garanticen límites válidos.

Memoryviews

Las memoryviews permiten trabajar con memoria contigua de NumPy y otros objetos compatibles sin copiar necesariamente los datos. Pueden representar vectores y matrices con tipos concretos. Revisa dimensiones, orden y continuidad antes de asumir que una operación será rápida.

Liberar el GIL

El Global Interpreter Lock protege operaciones de objetos Python. Cython puede liberar el GIL en código que trabaja exclusivamente con tipos C:

cdef long calcular(int limite) noexcept nogil:
    cdef int i
    cdef long total = 0
    for i in range(limite):
        total += i * i
    return total

No puedes manipular listas, diccionarios o cadenas Python normales sin el GIL. Liberarlo no acelera automáticamente un único hilo; permite paralelismo cuando el trabajo compilado es adecuado.

prange para paralelismo

prange puede distribuir iteraciones con OpenMP:

from cython.parallel cimport prange

cdef long total = 0
cdef int i
for i in prange(limite, nogil=True):
    # operación independiente
    pass

Configurar OpenMP varía por compilador. Además, las reducciones y escrituras compartidas deben diseñarse correctamente para evitar condiciones de carrera.

Integración con C

Cython puede importar declaraciones desde archivos .pxd y llamar bibliotecas C:

from libc.math cimport sqrt

cpdef double raiz(double valor):
    return sqrt(valor)

Esta capacidad resulta útil cuando existe una biblioteca madura que no tiene un wrapper Python.

Archivos .pxd

Los archivos .pxd funcionan de forma parecida a cabeceras: declaran tipos, funciones y clases de extensión. Separar interfaz e implementación mejora la reutilización entre módulos Cython.

La documentación oficial sobre archivos y compilación explica .pyx, .pxd, .pxi y opciones de construcción.

Generar un informe de anotación

Ejecuta:

cython -a calculos.pyx

El archivo HTML colorea líneas según la interacción con la API de Python. Las zonas con más amarillo suelen implicar más operaciones dinámicas. Este informe ayuda a decidir dónde añadir tipos.

Comparar rendimiento correctamente

Utiliza la misma entrada, repite ejecuciones y comprueba resultados. La guía sobre timeit en Python muestra cómo medir funciones pequeñas. Incluye también el costo de convertir datos si la versión Cython necesita preparar arrays.

Cython y NumPy

Antes de escribir bucles compilados, verifica si NumPy ya ofrece una operación vectorizada. Las bibliotecas numéricas ejecutan muchas operaciones en C y pueden ser más simples. Cython es especialmente útil cuando el algoritmo tiene lógica personalizada difícil de expresar con operaciones vectorizadas.

Empaquetado y distribución

Un paquete con extensiones compiladas necesita generar wheels para cada plataforma, versión de Python y arquitectura soportada. Los usuarios sin compilador pueden tener problemas si solo publicas una distribución fuente.

La gestión del proyecto con Poetry o herramientas basadas en pyproject.toml puede integrarse con el proceso, pero revisa la compatibilidad del backend de construcción.

Depuración

Mantén una versión Python de referencia y pruebas que comparen resultados. El código compilado puede fallar de maneras menos amigables si se desactivan comprobaciones. Empieza con seguridad completa, mide y desactiva controles únicamente en secciones verificadas.

Errores frecuentes

Los problemas comunes son compilar todo el proyecto sin perfilar, esperar mejoras sin añadir tipos, olvidar instalar un compilador, usar tipos demasiado pequeños, desactivar límites prematuramente y publicar sin wheels. También puede ocurrir que el cuello de botella esté en una base de datos o red, donde Cython no ayuda.

Buenas prácticas

Perfila primero, crea un benchmark, selecciona una función crítica, compílala sin alterar el comportamiento y añade tipos gradualmente. Conserva una interfaz Python sencilla, documenta los requisitos de construcción y automatiza pruebas en todas las plataformas soportadas.

Cython es una herramienta potente cuando se aplica a una parte bien identificada. No reemplaza algoritmos adecuados ni bibliotecas optimizadas, pero puede cerrar la distancia entre la productividad de Python y el rendimiento de C en cálculos específicos.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Uso do operador ternário em Python para condições rápidas
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Operador ternario en Python: guía clara y práctica

    Aprende el operador ternario en Python: sintaxis, asignaciones, listas, return, anidación, errores frecuentes y buenas prácticas.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Logo lambda usado no Half-Life
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Funciones lambda en Python: guía con ejemplos

    Aprende funciones lambda en Python con sorted, map, filter, closures, callbacks, type hints, errores comunes y criterios de legibilidad.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Como usar o comando return em funções Python
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Return en Python: cómo devolver valores correctamente

    Aprende cómo funciona return en Python, su diferencia con print, múltiples valores, None, type hints, excepciones y buenas prácticas.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Explicação prática de args e kwargs em funções Python
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Args y kwargs en Python: guía completa

    Aprende *args y **kwargs en Python, desempaquetado, parámetros flexibles, errores comunes, type hints y diseño de funciones claras.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Geração de números aleatórios seguros usando secrets em Python
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Números aleatorios seguros en Python con secrets

    Aprende secrets en Python para generar números, contraseñas y tokens seguros con randbelow, choice, token_hex, token_urlsafe y compare_digest.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026
    Uso do with para abrir arquivos com segurança em Python
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Sentencia with en Python: archivos seguros y contextos

    Aprende la sentencia with en Python para abrir archivos con seguridad, manejar errores, usar context managers, contextlib y varios recursos.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026