Inicio / programacion / Python 3.15 – acelera el arranque con importaciones perezosas

Python 3.15 – acelera el arranque con importaciones perezosas

Tarjeta del articulo sobre las importaciones perezosas de Python 3.15

Python 3.15 llega el 1 de octubre de 2026 y su cambio estrella son las importaciones perezosas (PEP 810): una nueva palabra clave lazy que difiere la carga de un módulo hasta su primer uso, para acelerar el arranque de tus programas. Si alguna vez abriste un CLI de Python y contaste los segundos antes de que respondiera, esto va de eso. Aquí vas a ver la sintaxis exacta de las importaciones perezosas en Python 3.15, cómo se comportan en tiempo de ejecución y qué más trae la versión.

Qué cambia con las importaciones perezosas

La sintaxis es una palabra clave suave, lazy, delante de la importación:

lazy import json
lazy from json import dumps

El módulo no se carga en esa línea. Se crea un objeto proxy ligado al nombre, y el módulo real se carga la primera vez que usas ese nombre. Puedes comprobarlo tú mismo:

import sys

lazy import json

print('json' in sys.modules)  # False - todavía no se cargó

# El primer uso dispara la carga
resultado = json.dumps({"hola": "mundo"})

print('json' in sys.modules)  # True - ahora sí

Con lazy from, cada nombre importado recibe su propio proxy. El primer uso de cualquiera de ellos carga el módulo completo, pero solo reifica ese nombre específico:

import sys

lazy from json import dumps, loads

print('json' in sys.modules)  # False

# Usar 'dumps' carga json y reifica SOLO 'dumps'
resultado = dumps({"hola": "mundo"})
print('json' in sys.modules)  # True

# Acceder a 'loads' ahora lo reifica (json ya está cargado)
datos = loads(resultado)

Un matiz importante: la importación perezosa difiere cuándo se carga un módulo, no qué se carga. Cuando el proxy se resuelve, el módulo entero se ejecuta igual que siempre.

Las reglas y los límites

Antes de usarlas en tu proyecto, conoce las restricciones de la PEP 810:

  • Solo funcionan a nivel de módulo. Dentro de funciones, cuerpos de clase o bloques try son un error de sintaxis.
  • Las star imports no se permiten: lazy from json import * no compila.
  • lazy from __future__ import ... tampoco existe.
  • Como lazy es una palabra clave suave, sigue funcionando como nombre de variable en cualquier otro contexto — solo tiene significado especial justo antes de un import.

Los errores también se comportan distinto, y esto conviene saberlo antes de que te sorprenda en producción:

  • Un módulo que no existe ya no falla en la línea del import, falla en el primer uso — con un traceback encadenado que muestra tanto la línea del import como la línea que lo disparó.
  • Un fallo no envenena el proxy: los accesos posteriores reintentan la importación.
  • Después de unos accesos, el intérprete adapta el bytecode y el costo se vuelve prácticamente cero. Un import reificado es indistinguible de uno normal.

Cómo afecta a tu código existente

Es un cambio opt-in: no tocas nada y tu código funciona igual. Pero si adoptas lazy, hay consecuencias prácticas que revisar:

  • Tus imports dejan de ser tu primera línea de defensa. Si tenías un import en la cabecera para validar que una dependencia existe, con lazy el fallo se mueve al primer uso — posiblemente en un path que tus tests no cubren.
  • Los CLIs ganan lo más. El caso de uso que motivó la PEP: herramientas de línea de comandos que importan librerías pesadas que solo se necesitan en algunas rutas. Diferir la carga es arranque más rápido para todos.
  • El import circular que estabas escondiendo puede aparecer. Si diferías un import dentro de una función precisamente por una dependencia circular, ahora tienes una herramienta de primera clase para eso — úsala sabiendo que es lo que estás haciendo.

Para probarlo hoy sin tocar tu versión del sistema, instala el candidato (no lo uses en producción todavía):

pyenv install 3.15.0rc2
pyenv local 3.15.0rc2

Lo demás que trae Python 3.15

Las importaciones perezosas son el titular, pero no vienen solas:

  • frozendict (PEP 814): un diccionario inmutable como tipo integrado — el equivalente de frozenset para dicts, útil como constante compartida y clave de otro dict.
  • sentinel (PEP 661): un tipo para valores centinela, para dejar de inventar object() como marcador de «sin valor».
  • Tachyon (PEP 799): un profiler estadístico de alta frecuencia integrado, dentro de un paquete dedicado a organizar las herramientas de profiling.
  • UTF-8 por defecto (PEP 686): Python deja de depender de la configuración regional para la codificación. Si trabajas con archivos en Latin-1 heredados, revísalo antes de migrar.
  • JIT más rápido: 8-9% de mejora geométrica en Linux x86-64 y 12-13% en macOS AArch64 sobre el intérprete estándar.
  • Punteros de frame activados por defecto (PEP 831): mejor observabilidad para profilers y herramientas de diagnóstico.

Cómo comprobar que lo aprovechas

Un ejercicio honesto antes de sembrar lazy por todo tu código: mide. Arranca tu programa con un perfil de arranque — el propio Tachyon sirve — anota cuánto tarda, aplica lazy a las importaciones pesadas que no se usan en el camino principal, y vuelve a medir. Si la mejora no se ve, no la uses ahí: el costo de legibilidad debe comprar algo real.

Fuentes: el anuncio de la RC2 en blog.python.org y la PEP 810 completa con la especificación de la sintaxis.

Etiquetado:

Deje un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *