Python sigue su ciclo de siempre: una versión mayor cada octubre, con mejoras en el lenguaje, la librería estándar y las entrañas del intérprete. Python 3.13 salió en octubre de 2024 y 3.14 lo hizo en octubre de 2025. Las dos merecen atención porque llevan cambios que llevan años discutiéndose, algunos con implicaciones bastante serias para el rendimiento y la seguridad.
El ciclo de versiones y qué cambia
Desde Python 3.9, el calendario es predecible: versión nueva en octubre, cinco años de soporte de seguridad. Eso significa que hoy conviven activamente 3.9, 3.10, 3.11, 3.12, 3.13 y ya tenemos 3.14. Para proyectos nuevos no hay excusa para usar menos de 3.11, que fue la versión que dio un salto importante en velocidad. Las de 3.12 y 3.13 refinan eso y añaden cosas nuevas.
A continuación van los cambios concretos, sin rodeos.
Python 3.13: el GIL ya no es obligatorio
Qué es el GIL y por qué molesta
El GIL (Global Interpreter Lock) es un mutex que impide que más de un hilo de Python ejecute bytecode a la vez. Existe desde los años 90 y su objetivo original era simplificar la gestión de memoria. El problema es que en 2024 los servidores tienen 32, 64 o 128 núcleos, y Python solo aprovecha uno en cargas de CPU intensiva aunque uses threading. Para eso están multiprocessing o librerías como NumPy que liberan el GIL internamente, pero no es lo mismo.
El PEP 703 propone un build alternativo del intérprete que funciona sin GIL. No elimina el GIL del CPython normal (eso rompería demasiadas extensiones C), sino que añade un binario separado: python3.13t, donde la t es de free-threaded.
Cómo probarlo
En distribuciones que lo empaquetan ya puedes instalarlo directamente. Con pyenv es así:
pyenv install 3.13t
pyenv local 3.13t
python --version
# Python 3.13.0 experimental free-threading build
Para comprobar que el GIL está desactivado:
import sys
print(sys._is_gil_enabled()) # False en el build free-threaded
Con el GIL desactivado, dos hilos que hagan trabajo de CPU real en paralelo ya no se bloquean entre sí. En benchmarks de código Python puro con cuatro hilos, los tiempos caen a la mitad o más comparado con CPython normal.
Limitaciones actuales
Que sea experimental no es solo marketing: todavía hay extensiones C que asumen que el GIL existe y que pueden romperse en el build free-threaded. NumPy, Cython y otras librerías populares han añadido soporte durante 2025, pero conviene revisar cada dependencia antes de lanzarte. Además, el propio CPython usa un sistema de conteo de referencias atómicas que añade algo de overhead incluso en código single-threaded.
Dicho esto, para código de procesamiento numérico o IO masivo sin librerías externas, ya funciona bien. Y la dirección es clara: el objetivo es que en 3.15 o 3.16 esto pase a ser estable.
El JIT experimental de Python (PEP 744)
Python 3.13 también incluye un compilador JIT, aunque para usarlo hay que compilar el intérprete con --enable-experimental-jit (o usar un paquete que lo traiga activado). La técnica que usa se llama copy-and-patch.
Qué es copy-and-patch
En lugar de generar código máquina desde cero como haría un JIT clásico, copy-and-patch trabaja con plantillas precompiladas de cada operación. Cuando el intérprete detecta un camino de código caliente, copia la plantilla y parchea los huecos con los valores concretos (direcciones de memoria, constantes). Es más sencillo de implementar que un JIT completo y produce código compilado muy rápido, aunque las optimizaciones son más limitadas.
El resultado en benchmarks actuales está entre el 5% y el 10% de mejora sobre el intérprete base. No es una revolución, pero el JIT de Python lleva menos de dos años en desarrollo. PyPy, que tiene un JIT maduro, tardó años en llegar a sus números actuales. La base ya está ahí.
Qué esperar en versiones futuras
En 3.14 el JIT ya gana velocidad adicional con optimizaciones de tipo type specialization más agresivas. La hoja de ruta apunta a que en 3.15 o 3.16 empiece a activarse por defecto en algunas plataformas. Si tienes código que lleva mucho tiempo en funciones Python puras (parsers, transformaciones de datos, algoritmos), es algo que conviene seguir de cerca.
El REPL mejorado de 3.13
Esto parece menor pero no lo es. El REPL interactivo de CPython era bastante básico comparado con ipython o ptpython. En 3.13 se reescribió por completo y ahora trae:
- Edición multilínea real: puedes pegar bloques de código, modificarlos y ejecutarlos sin que se rompa la indentación.
- Colores en la salida: errores en rojo, strings en verde, números destacados.
- Historial persistente entre sesiones.
- Atajos de teclado al estilo de editores de texto.
Para muchos flujos de trabajo de exploración o debugging rápido, ya no hace falta instalar nada extra. Prueba python3.13 y verás la diferencia.
Mejoras en mensajes de error y locals()
Mensajes de error más útiles
Python 3.10 fue el punto de inflexión con los mensajes de error mejorados. Desde entonces cada versión añade más contexto. En 3.13 los errores de tipo y los NameError incluyen sugerencias más precisas, y los tracebacks en código con decoradores son más fáciles de leer.
locals() y PEP 667
El comportamiento de locals() era confuso en determinados contextos: dentro de comprehensions, en funciones anidadas o al depurar con pdb, el diccionario que devolvía podía no reflejar el estado real de las variables. El PEP 667 lo corrige y hace que locals() devuelva siempre un snapshot coherente. Si usas locals() para introspección o para pasar variables a plantillas de texto, el comportamiento ahora es predecible.
TypeVar con defaults y @deprecated
PEP 696: TypeVar con valores por defecto
Hasta 3.12, si definías un genérico con un TypeVar, el llamador siempre tenía que especificar el tipo. En 3.13 los TypeVar pueden tener un valor por defecto:
from typing import TypeVar
T = TypeVar('T', default=str)
class Respuesta[T]:
def __init__(self, valor: T) -> None:
self.valor = valor
# Ahora puedes hacer esto sin especificar el tipo:
r = Respuesta("hola") # T se infiere como str por defecto
Es especialmente útil en librerías que quieren ofrecer un comportamiento por defecto razonable sin obligar al usuario a anotar todo.
@typing.deprecated (PEP 702)
Por fin hay un decorador oficial para marcar código como obsoleto:
from typing import deprecated
@deprecated("Usa nueva_funcion() en su lugar")
def funcion_vieja():
pass
Los editores y herramientas de análisis estático como mypy o Pylance ya lo reconocen y muestran la advertencia al llamar a la función. Hasta ahora cada librería inventaba su propia solución.
Python 3.14: las t-strings cambian cómo tratas texto dinámico
Este es el cambio más interesante de Python 3.14. Las template strings (t-strings, PEP 750) tienen una sintaxis igual que los f-strings pero con prefijo t. La diferencia está en lo que devuelven:
- Un f-string evalúa las expresiones y devuelve un
strnormal. - Una t-string devuelve un objeto
Templatecon las partes separadas: los fragmentos de texto literal y las expresiones evaluadas.
Por qué importa: SQL seguro sin librerías extra
El problema clásico de la interpolación de strings en SQL es la inyección. Con f-strings puedes cometer el error fácilmente:
# MAL: inyección SQL posible
nombre = input("Usuario: ")
query = f"SELECT * FROM users WHERE name = '{nombre}'"
Con t-strings y una función que procese el Template:
from string.templatelib import Template
def sql_seguro(template: Template) -> tuple[str, list]:
partes = []
valores = []
for parte in template:
if isinstance(parte, str):
partes.append(parte)
else:
partes.append("?")
valores.append(parte.value)
return "".join(partes), valores
nombre = input("Usuario: ")
query, params = sql_seguro(t"SELECT * FROM users WHERE name = {nombre}")
cursor.execute(query, params)
La función recibe el template sin procesar y puede decidir cómo manejar cada expresión: parametrizarla, escaparla o rechazarla. El usuario no puede inyectar SQL porque nunca llega como texto plano a la consulta.
Esto sirve igual para HTML (escape automático), i18n (extraer las cadenas para traducción sin perder contexto) o logging estructurado.
annotationlib y evaluación lazy de anotaciones
Python 3.14 también incluye annotationlib, un módulo nuevo para gestionar las anotaciones de tipo. Resuelve un problema de larga historia: las anotaciones se evaluaban en tiempo de importación, lo que causaba errores circulares y ralentizaba el arranque en módulos con muchas anotaciones. Con annotationlib la evaluación puede hacerse de forma perezosa, cuando se necesita, no antes.
Si usas mucho typing.get_type_hints() o tienes módulos con referencias circulares en las anotaciones, nota la diferencia en 3.14.
Cuándo migrar
Una guía rápida según el caso:
- Proyecto nuevo en 2026: usa 3.13 como mínimo. Si no tienes dependencias que rompan con el build free-threaded, prueba 3.13t para ver si tus workloads se benefician.
- Proyecto existente en 3.10 o 3.11: migra a 3.12 o 3.13 sin problema. Los cambios de compatibilidad entre esas versiones son mínimos.
- Proyecto en 3.9 o anterior: tienes deuda técnica. Python 3.9 sale de soporte en octubre de 2025. Muévete a 3.12 o 3.13 cuanto antes.
- Quieres t-strings: necesitas 3.14. La sintaxis es nueva y no hay backport.
- Tienes extensiones C propias o dependencias nativas poco habituales: prueba el build free-threaded en un entorno de test antes de comprometerte.
Si tienes dudas sobre el estado de salud de tu código Python antes de actualizar, puede interesarte ver cómo detectar memory leaks en Python con herramientas modernas. Y si estás empezando con la parte de herramientas y scripts, hay una guía sobre construir herramientas CLI ligeras con Python que viene bien antes de meterte en actualizaciones más complejas.
Lo interesante de este par de versiones es que los cambios más grandes no son de sintaxis sino de arquitectura interna: quitar el GIL y añadir un JIT son proyectos de varios años que ahora están disponibles para experimentar. Las t-strings de 3.14 resuelven un problema real de seguridad de forma elegante. No todas las versiones de Python cambian algo fundamental; estas dos sí lo hacen.
Imagen: Pexels / Marek Práil
