Cómo crear un sistema de recordatorios con alarma en Python

Publicado el: 11/07/2026
Tempo de leitura: 4 minutos
Sistema de lembretes e alarmes desenvolvido com Python

Un sistema de recordatorios con alarma permite registrar una fecha y una hora, esperar hasta el momento programado y avisar al usuario mediante sonido, mensaje o notificación. Este proyecto combina fechas, bucles, persistencia, validación y ejecución en segundo plano. Una versión útil debe sobrevivir a reinicios, evitar perder alarmas y manejar correctamente las zonas horarias.

Para seguir esta guía conviene conocer datetime en Python, el uso de threads, las funciones, el manejo de excepciones y el registro con logging.

La documentación oficial de datetime explica fechas, horas y diferencias temporales. La documentación oficial del módulo time describe pausas y relojes, aunque para alarmas basadas en calendario trabajaremos principalmente con datetime.

Crear un recordatorio simple

from datetime import datetime


def crear_recordatorio(texto, fecha_hora):
    return {
        "texto": texto.strip(),
        "fecha_hora": fecha_hora.isoformat(timespec="minutes"),
        "completado": False,
    }

Guardar la fecha en formato ISO facilita la lectura y recuperación. No guardes únicamente “dentro de 30 minutos”, porque después de reiniciar el programa necesitas un momento absoluto.

Leer fecha y hora

def leer_fecha_hora():
    while True:
        texto = input("Fecha y hora (AAAA-MM-DD HH:MM): ").strip()
        try:
            momento = datetime.strptime(texto, "%Y-%m-%d %H:%M")
        except ValueError:
            print("Formato inválido")
            continue

        if momento <= datetime.now():
            print("El momento debe estar en el futuro")
            continue
        return momento

Esta versión utiliza la hora local del equipo. Para una aplicación que opera en varios países, utiliza objetos conscientes de zona horaria con zoneinfo.

Esperar de manera controlada

Una implementación ingenua podría dormir durante horas. Es mejor comprobar periódicamente:

import time


def esperar_hasta(momento):
    while True:
        restante = (momento - datetime.now()).total_seconds()
        if restante <= 0:
            return
        time.sleep(min(restante, 30))

El intervalo máximo de treinta segundos permite reaccionar si el reloj cambia o si el programa necesita detenerse. Para muchas alarmas, no debes crear un bucle independiente por cada una; conviene mantener una cola ordenada.

Emitir una alarma

En Windows, winsound forma parte de la biblioteca estándar:

import winsound


def sonar_alarma():
    frecuencia = 1000
    duracion = 700
    for _ in range(3):
        winsound.Beep(frecuencia, duracion)

En otros sistemas puedes reproducir un archivo mediante una biblioteca compatible o mostrar una notificación. El núcleo de recordatorios no debe depender directamente del método de sonido.

def avisar(recordatorio, reproductor):
    print(f"\nRECORDATORIO: {recordatorio['texto']}")
    reproductor()

Guardar recordatorios en JSON

import json
from pathlib import Path

RUTA = Path("recordatorios.json")


def guardar_recordatorios(recordatorios):
    temporal = RUTA.with_suffix(".tmp")
    temporal.write_text(
        json.dumps(recordatorios, ensure_ascii=False, indent=2),
        encoding="utf-8",
    )
    temporal.replace(RUTA)


def cargar_recordatorios():
    if not RUTA.exists():
        return []
    try:
        datos = json.loads(RUTA.read_text(encoding="utf-8"))
    except (OSError, json.JSONDecodeError):
        return []
    return datos if isinstance(datos, list) else []

La escritura mediante un archivo temporal reduce el riesgo de corrupción. En una aplicación importante, registra el error en vez de ignorarlo silenciosamente.

Encontrar alarmas pendientes

def pendientes(recordatorios):
    return sorted(
        (r for r in recordatorios if not r.get("completado")),
        key=lambda r: r["fecha_hora"],
    )

El formato ISO ordena correctamente cuando todas las fechas siguen la misma zona y estructura.

Procesar la próxima alarma

def procesar_siguiente(recordatorios, reproductor):
    lista = pendientes(recordatorios)
    if not lista:
        return False

    proximo = lista[0]
    momento = datetime.fromisoformat(proximo["fecha_hora"])
    esperar_hasta(momento)
    avisar(proximo, reproductor)
    proximo["completado"] = True
    guardar_recordatorios(recordatorios)
    return True

Si el programa estuvo apagado y encuentra una alarma vencida, debes decidir si avisar inmediatamente, marcarla como perdida o preguntar al usuario.

Ejecutar sin bloquear el menú

Una interfaz gráfica se congelaría si llama a esperar_hasta en el hilo principal. Puedes usar un hilo trabajador:

from threading import Event, Thread

parar = Event()


def trabajador(recordatorios, reproductor):
    while not parar.is_set():
        ahora = datetime.now()
        for recordatorio in pendientes(recordatorios):
            momento = datetime.fromisoformat(recordatorio["fecha_hora"])
            if momento <= ahora:
                avisar(recordatorio, reproductor)
                recordatorio["completado"] = True
                guardar_recordatorios(recordatorios)
        parar.wait(15)


hilo = Thread(
    target=trabajador,
    args=(recordatorios, sonar_alarma),
    daemon=True,
)
hilo.start()

Event.wait permite detener el hilo sin esperar a que termine un sleep largo. Protege la lista con un lock si el menú y el trabajador pueden modificarla simultáneamente.

def agregar(recordatorios):
    texto = input("Recordatorio: ").strip()
    if not texto:
        print("El texto no puede estar vacío")
        return

    momento = leer_fecha_hora()
    recordatorios.append(crear_recordatorio(texto, momento))
    guardar_recordatorios(recordatorios)


def listar(recordatorios):
    for indice, item in enumerate(pendientes(recordatorios), start=1):
        print(f"{indice}. {item['fecha_hora']} - {item['texto']}")

Añade opciones para eliminar, posponer y marcar como completado. Para borrar, utiliza un identificador único en vez de depender de la posición visual.

Identificadores únicos

from uuid import uuid4


def crear_recordatorio(texto, fecha_hora):
    return {
        "id": str(uuid4()),
        "texto": texto.strip(),
        "fecha_hora": fecha_hora.isoformat(timespec="minutes"),
        "completado": False,
    }

Zonas horarias

from datetime import datetime
from zoneinfo import ZoneInfo

zona = ZoneInfo("America/Sao_Paulo")
momento = datetime(2026, 8, 20, 9, 0, tzinfo=zona)

Guarda el momento en UTC y conserva la zona del usuario para presentarlo. Evita mezclar datetimes conscientes y no conscientes porque Python no permite compararlos de forma segura.

Recordatorios recurrentes

Para una alarma diaria puedes calcular la próxima fecha después de completarla. No sumes siempre 24 horas si la zona aplica horario de verano; reconstruye la hora local del siguiente día y conviértela a UTC.

Notificaciones del sistema

Una mejora consiste en mostrar una notificación de escritorio. Mantén una interfaz de aviso genérica:

class Notificador:
    def enviar(self, titulo, mensaje):
        raise NotImplementedError

Después implementa adaptadores para sonido, correo, Telegram o notificación local sin modificar la lógica de programación.

Pruebas confiables

No esperes minutos reales durante los tests. Inyecta una función de reloj:

def esta_vencido(recordatorio, ahora):
    momento = datetime.fromisoformat(recordatorio["fecha_hora"])
    return momento <= ahora

Así puedes probar fechas pasadas, futuras y exactas. Simula también archivos corruptos, alarmas duplicadas, zona inválida y errores de reproducción.

Errores frecuentes

Los problemas habituales son usar un sleep de muchas horas, bloquear la interfaz, no guardar los datos, confiar en el reloj local sin zona, crear un thread por alarma y perder recordatorios después de un reinicio. También debes evitar reproducir sonido indefinidamente o no ofrecer una forma clara de detenerlo.

Conclusión

Un sistema de recordatorios confiable guarda momentos absolutos, valida las entradas, revisa periódicamente las alarmas y separa programación, persistencia y notificación. Empieza con JSON y una alarma local; luego añade zonas horarias, recurrencia, threads y una interfaz. Las pruebas deben controlar el reloj para ser rápidas y deterministas.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    texto Tkinter com uma interface gráfica dele ao lado
    Proyectos
    Foto de perfil de Leandro Hirt da Academify

    Cómo crear tu primera aplicación con Tkinter

    Crea tu primera aplicación con Tkinter: ventanas, ttk, formularios, grid, eventos, archivos, threads, estilos y separación de lógica.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Foto de uma pessoa usando uma calculadora
    Proyectos
    Foto de perfil de Leandro Hirt da Academify

    Cómo crear una calculadora en Python paso a paso

    Crea una calculadora en Python con funciones, menú, validación, Decimal, historial, pruebas y una base segura para añadir Tkinter.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Conversor de moedas desenvolvido com Python
    Proyectos
    Foto de perfil de Leandro Hirt da Academify

    Cómo crear un conversor de monedas con Python

    Crea un conversor de monedas con Python, Requests, Decimal, validación, caché, manejo de errores y tasas de referencia confiables.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026
    Landing page simples criada com Python e Tailwind CSS
    Proyectos
    Foto de perfil de Leandro Hirt da Academify

    Cómo crear una landing page con Python y Tailwind CSS

    Crea una landing page con Flask y Tailwind CSS: diseño responsivo, formularios, validación, SQLite, seguridad, SEO y despliegue.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Extração de dados de tabelas de sites usando Python e pandas
    Proyectos
    Foto de perfil de Leandro Hirt da Academify

    Cómo extraer tablas de sitios web con Python y Pandas

    Extrae tablas de sitios web con Pandas, Requests y Beautiful Soup, limpia columnas, pagina resultados y exporta datos de forma

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Integração de bots Discord com Python para automação
    Proyectos
    Foto de perfil de Leandro Hirt da Academify

    Cómo crear un bot de Discord con Python

    Crea un bot de Discord con Python y discord.py: comandos, slash commands, permisos, intents, Cogs, tareas, logs y seguridad del

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026