Guías
Backend Actualizado el 6 de noviembre de 2026

Python

Python 3 moderno: entornos virtuales, uv, estructuras de datos, f-strings, funciones, clases, errores, archivos, fechas con zona y herramientas.

  • #python
  • #uv
  • #pytest
  • #backend

Entornos virtuales (venv)

AcciónComando
Crear un entorno en .venv
Activar en Linux / macOS
Activar en Windows (PowerShell)
Activar en Windows (cmd)
Desactivar el entorno
Ver qué intérprete se está usando

Añade .venv/ a tu .gitignore: el entorno se recrea, no se versiona.

uv: gestor moderno

AcciónComando
Crear un proyecto nuevo (pyproject.toml)
Añadir una dependencia
Añadir una dependencia de desarrollo
Quitar una dependencia
Instalar todo según uv.lock
Ejecutar un script en el entorno del proyecto
Ejecutar una herramienta del proyecto
Crear un entorno virtual a mano
Instalar una versión de Python
Ejecutar una herramienta sin instalarla

pip básico

AcciónComando
Instalar un paquete
Instalar desde un archivo de requisitos
Congelar las versiones instaladas
Actualizar un paquete
Desinstalar un paquete
Listar paquetes desactualizados

Tipos y estructuras

TipoDescripción
listSecuencia ordenada y mutable: [1, 2, 3]
tupleSecuencia ordenada e inmutable: (1, 2)
dictPares clave-valor, mantiene el orden de inserción: {"a": 1}
setElementos únicos sin orden: {1, 2, 3}
x[-1] / x[1:3]Último elemento / slice del índice 1 al 2
d.get("k", 0)Leer una clave con valor por defecto, sin KeyError
a, *rest = itemsDesempaquetar el primero y el resto
python
nums = [1, 2, 3, 4, 5]
squares = [n * n for n in nums if n % 2 == 0]   # [4, 16]
by_id = {u["id"]: u for u in users}              # dict comprehension
unique = {w.lower() for w in words}              # set comprehension
total = sum(n for n in nums)                     # generator expression

for i, name in enumerate(["ana", "luis"], start=1):
    print(i, name)
for name, age in zip(names, ages):
    print(f"{name}: {age}")

Strings y f-strings

ExpresiónResultado
f"{price:.2f}"Dos decimales: 19.90
f"{1234567:,}"Separador de miles: 1,234,567
f"{0.256:.1%}"Porcentaje: 25.6%
f"{7:03d}"Relleno con ceros: 007
f"{name:>10}"Alinear a la derecha en 10 caracteres
f"{now:%Y-%m-%d %H:%M}"Formatear una fecha
f"{value=}"Depuración: imprime value=42
", ".join(items) / s.split(",")Unir y separar strings

Funciones

python
def greet(name: str, greeting: str = "Hola", *, upper: bool = False) -> str:
    """Return a greeting. Arguments after * are keyword-only."""
    text = f"{greeting}, {name}"
    return text.upper() if upper else text


def log(*args: object, **kwargs: object) -> None:
    print("args:", args, "kwargs:", kwargs)


greet("Ana", upper=True)          # 'HOLA, ANA'
log(1, 2, level="info")           # args: (1, 2) kwargs: {'level': 'info'}

Nunca uses un valor mutable como defecto (def f(items=[])): usa None y créalo dentro de la función.

Clases y dataclasses

python
from dataclasses import dataclass, field
from datetime import datetime, timezone


@dataclass(frozen=True)
class User:
    id: int
    email: str
    roles: list[str] = field(default_factory=list)
    created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))

    @property
    def is_admin(self) -> bool:
        return "admin" in self.roles


user = User(id=1, email="ana@example.com", roles=["admin"])
print(user.is_admin, user)

@dataclass genera __init__, __repr__ y __eq__; frozen=True lo hace inmutable.

Errores y context managers

python
class ValidationError(Exception):
    """Raised when input data is invalid."""


try:
    value = int(raw)
except ValueError as exc:
    raise ValidationError(f"invalid number: {raw!r}") from exc
else:
    print("parsed", value)
finally:
    print("always runs")

# Context manager: closes the file even if an error occurs
with open("data.txt", encoding="utf-8") as f:
    first_line = f.readline()

Archivos y pathlib

AcciónCódigo
Ruta relativa al script actualPath(__file__).parent / "data.json"
Leer todo el textopath.read_text(encoding="utf-8")
Escribir textopath.write_text(text, encoding="utf-8")
Crear carpetas (con padres)path.mkdir(parents=True, exist_ok=True)
Buscar archivos recursivamentePath("src").rglob("*.py")
Comprobar si existepath.exists()
Nombre, extensión y nombre sin extensiónpath.name / path.suffix / path.stem

Todo con from pathlib import Path. Prefiere pathlib a os.path.

Fechas con zona horaria

python
from datetime import datetime, timedelta, timezone
from zoneinfo import ZoneInfo

now = datetime.now(timezone.utc)                 # always store in UTC
stamp = now.isoformat()                          # '2026-11-06T14:32:00.123456+00:00'

parsed = datetime.fromisoformat("2026-11-06T14:32:00Z")
tomorrow = now + timedelta(days=1)

# Convert to local time only to display it
local = now.astimezone(ZoneInfo("America/Mexico_City"))
print(local.strftime("%d/%m/%Y %H:%M"))

datetime.now() sin argumento devuelve una fecha naive (sin zona) que depende del servidor: evítala.

Módulos útiles de la stdlib

MóduloPara qué sirve
jsonjson.loads(text) / json.dumps(obj, indent=2)
collectionsCounter, defaultdict, deque, namedtuple
itertoolschain, groupby, batched, product, islice
functoolscache, lru_cache, partial, reduce
pathlibRutas y archivos orientados a objetos
loggingLogs con niveles en lugar de print
argparseParsear argumentos de línea de comandos
subprocesssubprocess.run(["ls", "-l"], check=True)

Herramientas: ruff, pytest y mypy

AcciónComando
Revisar el código (linter)
Corregir lo que se pueda automáticamente
Formatear el código
Ejecutar los tests
Tests verbosos, parando en el primer fallo
Ejecutar tests que coincidan con un nombre
Comprobar tipos
python
# tests/test_calc.py
import pytest

from calc import divide


def test_divide() -> None:
    assert divide(10, 2) == 5


def test_divide_by_zero() -> None:
    with pytest.raises(ZeroDivisionError):
        divide(1, 0)