Lección 0.2.1 · 35 min

Instalación de Python con uv: versiones y ciclo de soporte

Python no es uno: hay una versión nueva cada octubre y cada una vive cinco años. Esta lección instala la del curso con uv, explica qué significa que una versión esté «en soporte» y enseña a comprobar desde el propio código con qué intérprete se ejecuta.

Fig. — Ciclo de soporte de Python 3.10 a 3.15: dos años de correcciones, después solo seguridad, y fin a los cinco años
01/06
Módulo
0.2 · Entorno de trabajo moderno
Duración
35 min
Lecciones del nivel 0
  1. 0.1 · Bienvenida y expectativas

    1. 0.1.1 Trading sistemático, algorítmico y cuantitativo frente al discrecional
    2. 0.1.2 Expectativas realistas: costes, tiempo y riesgo de pérdida
    3. 0.1.3 Estructura del curso, tests de entrada, repositorio personal y aprendizaje con IA
  2. 0.2 · Entorno de trabajo moderno

    1. 0.2.1 Instalación de Python con uv: versiones y ciclo de soporte
    2. 0.2.2 Entornos virtuales y dependencias: uv init, uv add, pyproject.toml y lockfiles
    3. 0.2.3 Editores (VS Code, Cursor, PyCharm) y notebooks (Jupyter, JupyterLab, marimo)
    4. 0.2.4 Terminal básica, rutas, variables de entorno y ficheros .env
    5. 0.2.5 Git y GitHub: commits, ramas, pull requests y .gitignore
    6. 0.2.6 Introducción a los asistentes de código con IA: prompts, revisión y tests
  3. 0.3 · Fundamentos del lenguaje

    1. 0.3.1 Variables, tipos y operadores; coma flotante y decimal para precios y ticks
    2. 0.3.2 Cadenas, f-strings y formato de números y fechas
    3. 0.3.3 Listas, tuplas, diccionarios, conjuntos y comprensiones
    4. 0.3.4 Control de flujo: if, elif, else, for, while y match-case
    5. 0.3.5 Funciones: argumentos, *args y **kwargs, lambdas y ámbito
    6. 0.3.6 Excepciones; módulos y paquetes, con los imports perezosos de Python 3.15
  4. 0.4 · Python intermedio

    1. 0.4.1 Programación orientada a objetos: clases, herencia, composición y dataclasses
    2. 0.4.2 Tipado: type hints, mypy o ty y Pydantic para configuraciones
    3. 0.4.3 Iteradores, generadores, decoradores y context managers
    4. 0.4.4 Ficheros (CSV, JSON, YAML, TOML) y fechas con zonas horarias
    5. 0.4.5 Logging profesional y testing con pytest
    6. 0.4.6 Concurrencia: threading, multiprocessing, asyncio y free-threading
  5. 0.5 · Computación numérica y datos

    1. 0.5.1 NumPy 2: arrays, broadcasting, vectorización, álgebra lineal y generadores aleatorios
    2. 0.5.2 pandas 3.0: Series, DataFrame, índices temporales, Copy-on-Write, tipo str y pd.col()
    3. 0.5.3 Selección, filtrado, groupby, merge, pivot, resample y ventanas móviles
    4. 0.5.4 Polars: API lazy frente a eager, expresiones, rendimiento y cuándo elegirlo frente a pandas
    5. 0.5.5 DuckDB y SQL esencial: SELECT, JOIN, GROUP BY y funciones de ventana sobre Parquet
  6. 0.6 · Visualización

    1. 0.6.1 Matplotlib orientado a objetos, Seaborn y Plotly: gráficos de precios, drawdown y velas
    2. 0.6.2 Dashboards rápidos con Streamlit: un panel de seguimiento en un solo script
  7. 0.7 · Matemáticas y estadística mínimas

    1. 0.7.1 Rentabilidades simples y logarítmicas, interés compuesto y estadística descriptiva
    2. 0.7.2 Probabilidad y distribuciones, correlación frente a causalidad y regresión simple
    3. 0.7.3 Álgebra lineal intuitiva: vectores y matrices como preparación para carteras

Por qué importa la versión

Un programa de Python no se ejecuta solo: lo ejecuta un intérprete, el programa python que lee tu código y lo convierte en operaciones. Cada versión del intérprete añade funciones al lenguaje, cambia detalles de la biblioteca estándar y, con el tiempo, deja de recibir arreglos. Las librerías del curso (NumPy, pandas, Polars…) publican paquetes para unas versiones concretas y abandonan las antiguas.

Para quien hace trading sistemático, esto tiene tres consecuencias prácticas:

  • Reproducibilidad. Un backtest debe dar el mismo resultado hoy y dentro de un año. Si el intérprete o una librería cambian, un cálculo puede cambiar con ellos: un valor por defecto distinto, un redondeo, un aviso que antes no salía.
  • Seguridad. Un sistema en real se conecta a un bróker con claves de API. Si su intérprete ya no recibe parches de seguridad, cualquier fallo que se descubra quedará abierto para siempre.
  • Compatibilidad. Lo nuevo de las librerías llega primero a las versiones recientes. Quedarse en una versión antigua acaba dejando fuera de las mejoras de pandas 3.0 o NumPy 2 (módulo 0.5).

El curso usa Python 3.14 (en concreto 3.14.8, la versión con la que se ha ejecutado todo el código que verás). 3.13 también sirve. Esta lección explica por qué y cómo instalarla.

El ciclo de vida de una versión

Desde 2019, Python publica una versión nueva cada año, en octubre (PEP 602). Cada versión pasa por cinco fases, que la guía de desarrollo de Python describe así1Nota 1 · Python Developer's Guide, «Status of Python versions» (devguide.python.org/versions), consultada el 21 de octubre de 2026. Las fechas de fin de soporte desde 3.11 son previstas y las ajustan los responsables de cada versión.:

primera betaversión finala los dos añosa los cinco añosfeatureprereleasebugfixsecurityeol
Fuente Mermaid
stateDiagram-v2
  [*] --> feature
  feature --> prerelease: primera beta
  prerelease --> bugfix: versión final
  bugfix --> security: a los dos años
  security --> eol: a los cinco años
  eol --> [*]
  • feature y prerelease: la versión está en desarrollo. Las betas y candidatas sirven para probar librerías, no para trabajar.
  • bugfix: la versión ya es estable. Recibe arreglos de errores y de seguridad, con instaladores nuevos aproximadamente cada dos meses (3.14.1, 3.14.2…). Dura unos dos años desde 3.13; en las anteriores, 18 meses.
  • security: solo parches de seguridad, publicados como código fuente y sin instaladores.
  • end-of-life (eol): a los cinco años de la publicación, el soporte termina. El intérprete sigue funcionando, pero nadie lo arregla.

La figura de la cabecera dibuja ese ciclo para las versiones de 3.10 a 3.15, con una línea en octubre de 2026. La barra gruesa es la fase de correcciones; la fina, la de solo seguridad. Las fechas, de la guía de desarrollo:

VersiónPublicadaFase en octubre de 2026Fin de soporte
3.104 oct 2021Fin de soporte1 oct 2026
3.1124 oct 2022Solo seguridadoct 2027 (previsto)
3.122 oct 2023Solo seguridadoct 2028 (previsto)
3.137 oct 2024Solo seguridadoct 2029 (previsto)
3.147 oct 2025Correccionesoct 2030 (previsto)
3.159 oct 2026Correccionesoct 2031 (previsto)

Dos fechas de este mes cambian el mapa. El 1 de octubre de 2026, Python 3.10 llegó al final de su soporte: si algún servidor o tutorial antiguo lo usa, es momento de migrar. El 9 de octubre se publicó Python 3.15.02Nota 2 · Notas de la versión de Python 3.15.0, python.org, 9 de octubre de 2026., que entre otras novedades usa UTF-8 como codificación por defecto e introduce los imports perezosos explícitos (lección 0.3.6).

Instalar uv y Python

uv es un gestor de proyectos y paquetes de Python escrito en Rust por Astral. Sustituye a varias herramientas clásicas (pip, venv, pyenv, pip-tools) con una sola, mucho más rápida. En este curso hace dos cosas: instalar versiones de Python (esta lección) y gestionar los entornos y las dependencias de cada proyecto (lección 0.2.2).

Se instala con un script oficial. En Linux y macOS, desde la terminal (la terminal se ve con más calma en la lección 0.2.4; por ahora basta con copiar y pegar):

curl -LsSf https://astral.sh/uv/install.sh | sh

En Windows, desde PowerShell:

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

Si prefieres un gestor de paquetes del sistema, también vale brew install uv (macOS) o winget install --id=astral-sh.uv -e (Windows). Cierra y vuelve a abrir la terminal y comprueba que responde:

uv --version

Con uv instalado, instalar Python es un comando:

uv python install 3.14         # la última 3.14.x
uv python list                 # versiones instaladas y disponibles
python3.14 --version           # uv deja un ejecutable con la versión
uv python upgrade 3.14         # pasar a la última 3.14.x más adelante

uv descarga una distribución de Python ya compilada y la guarda en su propia carpeta. No sobrescribe nada:

  • Linux: la distribución trae su propio Python, que usan herramientas del sistema. No lo actualices ni instales paquetes en él con sudo pip; un cambio ahí puede romper el gestor de paquetes del sistema.
  • macOS: puede haber un python3 de las herramientas de Xcode, normalmente antiguo. Déjalo estar.
  • Windows: no hace falta el instalador de python.org ni la tienda de Microsoft si usas uv.

Tampoco hace falta instalar Python a mano antes de empezar un proyecto: si un proyecto pide 3.14 y no la tienes, uv la descarga al ejecutar el primer comando. En la práctica casi nunca llamarás a python directamente, sino a uv run python dentro de un proyecto, que elige la versión correcta por ti (lección 0.2.2).

Para fijar la versión de una carpeta, uv python pin 3.14 crea en ella un fichero .python-version con el número. uv lo lee cada vez que trabajas en esa carpeta, y otras herramientas también lo entienden. El proyecto del curso lo tendrá desde el primer momento (lección 0.2.2).

Comprobar el intérprete desde Python

Instalar es la mitad. La otra mitad es saber, desde el propio código, con qué intérprete se está ejecutando: en tu portátil, en un servidor o en el ordenador de otra persona. El módulo sys de la biblioteca estándar lo dice:

IN [01]python
import sys

sys.version_info
OUT [01]Versión del intérprete
sys.version_info(major=3, minor=14, micro=8, releaselevel='final', serial=0)

sys.version_info es una tupla con nombre: versión mayor, menor y de corrección (micro), y el nivel de la versión (final en una versión estable; alpha, beta o candidate en una de prueba). Al ser una tupla, se puede comparar con otra tupla:

IN [02]python
print(sys.version_info[:2])
print(sys.version_info >= (3, 13))
print(sys.version_info >= (3, 15))
OUT [02]Comparar con una versión mínima
(3, 14)
True
False

El módulo platform añade el resto: la versión como texto, la implementación (CPython es la de referencia, la que instala uv) y el sistema operativo y la arquitectura de la máquina. En Linux, platform.system() devuelve Linux; en macOS, Darwin; en Windows, Windows. La salida de abajo es la de la máquina donde se ejecutó el curso:

IN [03]python
import platform

print("Python:", platform.python_version())
print("Implementación:", platform.python_implementation())
print("Sistema:", platform.system(), platform.machine())
OUT [03]Implementación y plataforma
Python: 3.14.8
Implementación: CPython
Sistema: Linux x86_64

Versiones como tuplas, no como texto

Un error clásico al trabajar con versiones es compararlas como cadenas de texto. Python compara las cadenas carácter a carácter, y el carácter «1» va antes que el «9»:

IN [04]python
versiones = ["3.9", "3.10", "3.14", "3.13"]
print(sorted(versiones))
print("3.9" > "3.10")
OUT [04]El error de comparar texto
['3.10', '3.13', '3.14', '3.9']
True

Según el texto, 3.9 es más moderna que 3.10. Es el mismo problema que ordenar fechas escritas como «9/3/2025» o importes guardados como texto: el orden parece razonable hasta que deja de serlo. La solución es convertir cada versión en una tupla de enteros antes de compararla:

IN [05]python
def como_tupla(version: str) -> tuple[int, ...]:
    """'3.10' -> (3, 10)"""
    return tuple(int(parte) for parte in version.split("."))

print(sorted(versiones, key=como_tupla))
print(como_tupla("3.9") > como_tupla("3.10"))
print(max(versiones, key=como_tupla))
OUT [05]Ordenar versiones como tuplas
['3.9', '3.10', '3.13', '3.14']
False
3.14

Las tuplas se comparan elemento a elemento: primero el 3 con el 3 y, como empatan, el 9 con el 10, esta vez como números. Por eso sys.version_info es una tupla y no un texto. La biblioteca packaging, que usan pip y uv por dentro, hace lo mismo con versiones más complejas («2.5.4», «3.0.0rc1»), pero para comparar versiones de Python basta con la tupla.

Qué versiones tienen soporte hoy

Con la tabla de antes se puede calcular cuántos meses de soporte le quedan a cada versión en una fecha dada. Se usa una fecha fija (21 de octubre de 2026) para que el resultado no cambie según el día en que ejecutes la celda; los fines de soporte de la guía de desarrollo vienen como año y mes:

IN [06]python
fin_soporte = {
    "3.10": (2026, 10), "3.11": (2027, 10), "3.12": (2028, 10),
    "3.13": (2029, 10), "3.14": (2030, 10), "3.15": (2031, 10),
}
hoy = (2026, 10)

for version, (anio, mes) in fin_soporte.items():
    meses = (anio - hoy[0]) * 12 + (mes - hoy[1])
    estado = "sin soporte" if meses <= 0 else f"{meses} meses"
    print(f"Python {version:>5}: {estado}")
OUT [06]Meses de soporte restantes
Python  3.10: sin soporte
Python  3.11: 12 meses
Python  3.12: 24 meses
Python  3.13: 36 meses
Python  3.14: 48 meses
Python  3.15: 60 meses

Para un proyecto nuevo, la regla práctica: la versión más reciente con al menos unos meses de rodaje y todas las librerías disponibles. Para un sistema en real, además, una versión a la que le queden años de soporte, porque migrar un sistema que opera cuesta más que migrar un notebook.

La versión, junto a los resultados

Un backtest produce números: rentabilidad, volatilidad, drawdown. Esos números dependen de los datos, del código y del entorno. El código lo guardará Git (lección 0.2.5) y los datos, tu carpeta datos/; el entorno hay que anotarlo. Un diccionario con las versiones, guardado junto a cada resultado, basta para empezar:

IN [07]python
import json
import numpy as np
import pandas as pd

entorno = {
    "python": platform.python_version(),
    "implementacion": platform.python_implementation(),
    "sistema": platform.system(),
    "numpy": np.__version__,
    "pandas": pd.__version__,
}
print(json.dumps(entorno, indent=2))
OUT [07]Metadatos del entorno de un backtest
{
  "python": "3.14.8",
  "implementacion": "CPython",
  "sistema": "Linux",
  "numpy": "2.5.4",
  "pandas": "3.0.6"
}

Si dentro de seis meses el mismo backtest da otro Sharpe, lo primero es comparar este bloque con el actual. La lección 0.2.2 va un paso más allá: fija las versiones exactas de todas las librerías en un fichero (uv.lock) para que el entorno sea idéntico en cualquier máquina.

Ejercicios

  1. Instala uv y Python 3.14 en tu ordenador. Ejecuta uv python list y anota qué versiones de Python tenías ya instaladas antes (las del sistema) y dónde están.
Solución

La salida depende de tu máquina. En Linux suele aparecer el Python del sistema en /usr/bin/python3 (la versión que traiga tu distribución) y la 3.14 de uv en una carpeta de tu usuario. En macOS puede aparecer el python3 de las herramientas de Xcode y, si usas Homebrew, el suyo. En Windows, solo las que hayas instalado tú. Lo importante: el Python del sistema sigue ahí y no lo has tocado.

  1. Escribe una función exigir_python(minima) que reciba una tupla como (3, 13) y lance un RuntimeError con un mensaje claro si el intérprete es más antiguo. ¿Dónde la llamarías en un sistema que opera en real?
Solución
IN [08]python
def exigir_python(minima: tuple[int, int]) -> None:
    actual = sys.version_info[:2]
    if actual < minima:
        raise RuntimeError(
            f"Se necesita Python {minima[0]}.{minima[1]} o superior; "
            f"este es {actual[0]}.{actual[1]}"
        )

exigir_python((3, 13))
print("Versión correcta")
OUT [08]Exigir una versión mínima
Versión correcta

Al principio del programa, antes de conectar con el bróker o de cargar datos: es mejor que el sistema no arranque a que arranque con un intérprete en el que nadie lo ha probado. Las excepciones se ven en la lección 0.3.6.

  1. Amplía la celda de los metadatos del entorno con la fecha y hora de ejecución en UTC y guárdala en un fichero entorno.json. ¿Por qué en UTC y no en la hora local?
Solución
IN [09]python
from datetime import datetime, timezone
from pathlib import Path

entorno["ejecutado_utc"] = datetime(2026, 10, 21, 16, 30,
                                    tzinfo=timezone.utc).isoformat()
Path("entorno.json").write_text(json.dumps(entorno, indent=2))
print(json.loads(Path("entorno.json").read_text())["ejecutado_utc"])
OUT [09]Metadatos con fecha en UTC
2026-10-21T16:30:00+00:00

En tu código usarías datetime.now(timezone.utc); aquí la fecha es fija para que la salida sea siempre la misma. UTC porque es la misma en todas las máquinas y no tiene cambios de horario: un servidor en Fráncfort, otro en Virginia y tu portátil escriben la misma hora para el mismo instante. Las zonas horarias de los mercados se ven en la lección 0.4.4.

Footnotes

  1. Python Developer's Guide, «Status of Python versions» (devguide.python.org/versions), consultada el 21 de octubre de 2026. Las fechas de fin de soporte desde 3.11 son previstas y las ajustan los responsables de cada versión. ↩

  2. Notas de la versión de Python 3.15.0, python.org, 9 de octubre de 2026. ↩

Respuesta plegada en cada pregunta

Autoevaluación

  1. Un servidor que ejecuta tu sistema en real tiene Python 3.10. ¿Qué ha cambiado desde el 1 de octubre de 2026?

    • ANada: el código sigue funcionando y seguirá recibiendo parches
    • BPython 3.10 ha dejado de recibir correcciones, incluidas las de seguridad
    • CPython 3.10 deja de funcionar en Linux
    • Dpip ya no puede instalar paquetes en 3.10
    Ver respuesta

    Respuesta B. Python 3.10 ha dejado de recibir correcciones, incluidas las de seguridad

    El fin de soporte no apaga nada: el intérprete sigue funcionando. Lo que se acaba son los parches, también los de seguridad, y poco a poco las librerías dejan de publicar versiones para él. Un sistema en real no debería depender de una versión sin soporte.

  2. ¿Qué devuelve sorted(["3.9", "3.10", "3.14"])?

    • A['3.9', '3.10', '3.14']
    • B['3.10', '3.14', '3.9']
    • C['3.14', '3.10', '3.9']
    • DUn error, porque no son números
    Ver respuesta

    Respuesta B. ['3.10', '3.14', '3.9']

    Las cadenas se comparan carácter a carácter: «1» va antes que «9», así que «3.10» y «3.14» van antes que «3.9». Las versiones se comparan como tuplas de enteros, como sys.version_info.

  3. ¿En qué fase está Python 3.14 en octubre de 2026?

    • ADesarrollo (feature)
    • BCorrecciones (bugfix): recibe arreglos de errores y de seguridad, con instaladores cada dos meses aproximadamente
    • CSolo seguridad
    • DFin de soporte
    Ver respuesta

    Respuesta B. Correcciones (bugfix): recibe arreglos de errores y de seguridad, con instaladores cada dos meses aproximadamente

    Se publicó el 7 de octubre de 2025 y las versiones desde la 3.13 tienen unos dos años de correcciones. Pasará a solo seguridad en torno a octubre de 2027 y su soporte termina en octubre de 2030.

  4. ¿Por qué conviene guardar la versión de Python, NumPy y pandas junto a los resultados de un backtest?

    • APorque lo exige la normativa
    • BPara poder reproducir el resultado: un cambio de versión puede cambiar un cálculo, un valor por defecto o el rendimiento
    • CPara que el backtest vaya más rápido
    • DNo sirve para nada si el código está en Git
    Ver respuesta

    Respuesta B. Para poder reproducir el resultado: un cambio de versión puede cambiar un cálculo, un valor por defecto o el rendimiento

    Git guarda el código, no el intérprete ni las librerías. Si un resultado cambia al repetirlo meses después, la primera pregunta es si cambió el entorno. La lección 0.2.2 resuelve el problema de raíz con un lockfile.

Ideas clave

  • Cada octubre sale una versión de Python. Tiene unos dos años de correcciones, después solo parches de seguridad, y su soporte termina a los cinco años.
  • En octubre de 2026: 3.10 sin soporte desde el día 1, 3.15 publicada el día 9; el curso usa 3.14 y 3.13 también sirve.
  • uv instala y gestiona versiones de Python sin tocar el Python del sistema: uv python install 3.14.
  • sys.version_info es una tupla: compárala con (3, 13), nunca compares versiones como texto.
  • Un resultado de backtest sin la versión del entorno no es reproducible: guárdala junto a los números.

Recursos