25. Comando para detener programa

 

25. Comando para Detener Programa: Tutorial para Principiantes

⏹️ Introducción: El botón de "apagado" de tu asistente

¡Todo buen asistente necesita un botón de salida! Hasta ahora has estado cerrando tu asistente manualmente, pero es mucho más elegante poder decirle "detente" o "salir" y que termine su ejecución limpiamente. Es como enseñarle a tu asistente a despedirse cuando ya no lo necesitas.

Analoǵía: Tu asistente es como una conversación telefónica:

  • Iniciar el programa = Llamar por teléfono

  • Hablar comandos = Conversar normalmente

  • Comando de salida = Decir "adiós" y colgar


🔄 ¿Por qué es importante tener un comando de salida?

Razones principales:

  1. Experiencia de usuario: Es más natural decir "adiós" que cerrar la ventana

  2. Limpieza: Permite cerrar recursos adecuadamente

  3. Seguridad: Evita procesos colgados en segundo plano

  4. Profesionalismo: Los programas bien hechos tienen salidas elegantes

Esquema del ciclo de vida del asistente:

text

🚀 INICIO → Programa se ejecuta

     ↓

🎤 ESCUCHA → Espera comandos

     ↓

🤖 PROCESA → Ejecuta funciones

     ↓

🔄 REPITE → Vuelve a escuchar

     ↓

⏹️ SALIDA → (Cuando dices "detener")

     ↓

✅ FIN → Programa termina limpiamente


✍️ Código paso a paso explicado

Paso 1: Detectar cuando queremos salir

python

# En tu función principal (el loop infinito):

if 'detener programa' in comando or 'salir' in comando:

    hablar("Hasta luego, que tengas un buen día")

    quit()

Ejemplos que activarán la salida:

  • "detener programa"

  • "salir"

  • "terminar"

  • "adiós"

  • "hasta luego"

  • "cerrar asistente"


Paso 2: Entender quit()

python

# ¿Qué hace quit()?

quit()  # ← Termina el programa inmediatamente


# Equivalente a:

exit()  # ← También funciona

sys.exit()  # ← Versión más controlada (necesita import sys)

¿Cuál es la diferencia?

  • quit() y exit() son iguales, diseñados para el intérprete interactivo

  • sys.exit() es más apropiado para programas, permite pasar códigos de salida


Paso 3: Implementación básica

python

def verificar_salida(comando):

    """

    Verifica si el usuario quiere salir del programa

    """

    palabras_salida = [

        'detener programa',

        'salir',

        'terminar',

        'adiós',

        'hasta luego',

        'cerrar',

        'finalizar',

        'parar'

    ]

    

    for palabra in palabras_salida:

        if palabra in comando.lower():

            return True

    

    return False


# En tu loop principal:

if verificar_salida(comando):

    hablar("Hasta luego, que tengas un buen día")

    quit()


🎯 Código completo mejorado

python

# ASISTENTE VIRTUAL - COMANDO DE SALIDA

import sys

import pyttsx3


# Configuración de voz

engine = pyttsx3.init()


def hablar(texto):

    engine.say(texto)

    engine.runAndWait()


def despedirse():

    """

    Función de despedida elegante

    """

    mensajes_despedida = [

        "Hasta luego, que tengas un excelente día",

        "Adiós, ha sido un placer ayudarte",

        "Nos vemos pronto, cuídate",

        "Hasta la próxima, no dudes en llamarme",

        "Cerrando asistente, que todo te vaya bien"

    ]

    

    import random

    mensaje = random.choice(mensajes_despedida)

    

    # Opcional: Estadísticas de uso

    print(f"\n{'='*50}")

    print("📊 RESUMEN DE SESIÓN")

    print(f"{'='*50}")

    print("¡Gracias por usar el asistente virtual!")

    print(f"Último mensaje: {mensaje}")

    print(f"{'='*50}\n")

    

    hablar(mensaje)

    

    # Cerrar recursos antes de salir

    engine.stop()

    

    # Salir del programa

    sys.exit(0)  # 0 significa "salida exitosa"


def verificar_comando_salida(comando):

    """

    Verifica de forma inteligente si el usuario quiere salir

    """

    comando_lower = comando.lower()

    

    # Diccionario de comandos de salida con "peso"

    comandos_salida = {

        'detener programa': 10,      # Muy específico

        'salir': 8,                  # Claro y directo

        'terminar programa': 9,      # Específico

        'adiós': 7,                  # Amigable

        'hasta luego': 6,            # Amigable

        'cerrar asistente': 9,       # Específico

        'finalizar': 7,              # Formal

        'parar': 6,                  # Directo

        'basta': 5,                  # Más vago

        'detente': 6,                # Vago pero posible

    }

    

    # Buscar coincidencias

    mejor_coincidencia = None

    mejor_puntaje = 0

    

    for frase, puntaje in comandos_salida.items():

        if frase in comando_lower:

            # Verificar si es exacto o contiene

            palabras_usuario = comando_lower.split()

            palabras_frase = frase.split()

            

            # Si todas las palabras de la frase están en el comando

            if all(palabra in palabras_usuario for palabra in palabras_frase):

                if puntaje > mejor_puntaje:

                    mejor_puntaje = puntaje

                    mejor_coincidencia = frase

    

    # Si encontramos una buena coincidencia

    if mejor_coincidencia and mejor_puntaje >= 5:

        return True, mejor_coincidencia

    

    return False, None


def asistente_con_modo_confirmacion():

    """

    Asistente que pide confirmación antes de salir

    """

    hablar("Asistente virtual activado. Di 'ayuda' para ver comandos.")

    

    while True:

        # Escuchar comando

        comando = escuchar()

        

        if not comando:

            continue

        

        # Verificar si quiere salir

        quiere_salir, comando_detectado = verificar_comando_salida(comando)

        

        if quiere_salir:

            hablar(f"Entendí '{comando_detectado}'. ¿Estás seguro de que quieres salir?")

            

            respuesta = escuchar().lower()

            

            if any(palabra in respuesta for palabra in ['sí', 'si', 'afirmativo', 'correcto']):

                despedirse()

            else:

                hablar("Continuando con el asistente")

                continue

        

        # Otros comandos aquí...

        elif 'ayuda' in comando:

            mostrar_ayuda()

        

        elif 'hora' in comando:

            decir_hora()


# Función principal alternativa con salida más inteligente

def ejecutar_asistente():

    """

    Versión completa del asistente con manejo elegante de salida

    """

    import time

    

    # Estadísticas de la sesión

    inicio_sesion = time.time()

    comandos_ejecutados = 0

    

    hablar("¡Hola! Soy tu asistente virtual. Di 'ayuda' para ver qué puedo hacer.")

    

    try:

        while True:

            print("\n" + "─" * 50)

            print("🎤 Escuchando... (di 'salir' para terminar)")

            print("─" * 50)

            

            comando = escuchar()

            

            if not comando:

                continue

            

            # Mostrar lo que entendió

            print(f"👤 Tú: {comando}")

            

            # Incrementar contador

            comandos_ejecutados += 1

            

            # Verificar salida

            if verificar_comando_salida(comando)[0]:

                # Calcular tiempo de sesión

                tiempo_sesion = time.time() - inicio_sesion

                minutos = int(tiempo_sesion // 60)

                segundos = int(tiempo_sesion % 60)

                

                # Mensaje de resumen

                hablar(f"Sesión terminada. Ejecuté {comandos_ejecutados} comandos en {minutos} minutos y {segundos} segundos.")

                time.sleep(1)  # Pausa para que se escuche

                

                despedirse()

            

            # Procesar otros comandos

            procesar_comando(comando)

            

    except KeyboardInterrupt:

        # Si el usuario presiona Ctrl+C

        print("\n\n⚠️  Interrupción por teclado detectada")

        hablar("Interrupción detectada, cerrando asistente")

        sys.exit(1)

    

    except Exception as e:

        # Cualquier otro error

        print(f"\n❌ Error inesperado: {e}")

        hablar("Ha ocurrido un error, cerrando asistente")

        sys.exit(1)


# Diagrama visual del proceso de salida:

"""

🔄 LOOP PRINCIPAL: while True:

     ↓

🎤 ESCUCHA: "detener programa"

     ↓

🤖 ANALIZA: Verifica lista de comandos de salida

     ↓

✅ COINCIDE: Encuentra "detener programa"

     ↓

🗣️  RESPUESTA: "Hasta luego, que tengas un buen día"

     ↓

🛑 QUIT(): Termina ejecución

     ↓

📊 OPCIONAL: Muestra estadísticas de uso

     ↓

🎬 FIN: Programa termina limpiamente

"""


✨ Mejoras avanzadas para la salida

1. Guardar estado antes de salir:

python

def salir_con_estado():

    """Guarda información antes de salir"""

    import json

    

    estado = {

        "ultimo_comando": ultimo_comando,

        "hora_salida": time.strftime("%Y-%m-%d %H:%M:%S"),

        "comandos_ejecutados": contador_comandos

    }

    

    # Guardar en archivo

    with open("estado_asistente.json", "w") as f:

        json.dump(estado, f)

    

    hablar("Estado guardado. Hasta luego")

    quit()

2. Modo suspensión en vez de salida:

python

def modo_suspension():

    """En vez de salir, suspende temporalmente"""

    hablar("Entrando en modo suspensión. Di 'hola' para reactivar")

    

    while True:

        comando = escuchar()

        if 'hola' in comando or 'despertar' in comando:

            hablar("¡Hola de nuevo! ¿En qué puedo ayudarte?")

            return  # Vuelve al loop principal

    

    # El programa sigue corriendo pero "dormido"

3. Salida programada:

python

def salida_automatica(tiempo_minutos=30):

    """Sale automáticamente después de inactividad"""

    import time

    

    ultima_actividad = time.time()

    

    while True:

        if time.time() - ultima_actividad > tiempo_minutos * 60:

            hablar("Demasiado tiempo inactivo, cerrando asistente")

            quit()

        

        # Resto del código...

        if hay_comando:

            ultima_actividad = time.time()  # Reinicia el temporizador


🚨 Problemas comunes y soluciones

Problema 1: quit() no funciona en algunos editores

python

# Algunos editores bloquean quit()

# Solución alternativa:

import sys

sys.exit(0)  # Siempre funciona

Problema 2: El programa no cierra completamente

python

# Puede quedar algún hilo o proceso

# Solución: Limpiar recursos


def salida_completa():

    # Detener motor de voz

    engine.stop()

    

    # Cerrar archivos abiertos

    # (si tienes alguno)

    

    # Terminar procesos hijos

    # (si lanzaste algún programa)

    

    # Finalmente salir

    sys.exit(0)

Problema 3: Falsos positivos

python

# El usuario dice "no quiero salir" y se cierra

# Solución: Mejorar la verificación


def es_comando_salida_real(comando):

    # Filtrar negaciones

    negaciones = ['no', 'no quiero', 'no me', 'cancelar']

    

    for negacion in negaciones:

        if negacion in comando.lower():

            return False  # No es un comando de salida real

    

    # Resto de la verificación...


📊 Códigos de salida estándar

python

# Los códigos de salida indican cómo terminó el programa:

sys.exit(0)   # ✅ Éxito - Todo salió bien

sys.exit(1)   # ❌ Error general

sys.exit(2)   # ❌ Uso incorrecto

sys.exit(130) # ⚠️  Interrupción (Ctrl+C)


# ¿Por qué importan?

# - Otros programas pueden detectarlos

# - Scripts de sistema pueden reaccionar

# - Más profesional


✅ Resumen clave

  1. quit() o sys.exit() terminan el programa

  2. Verificar múltiples frases para mayor flexibilidad

  3. Confirmación opcional evita salidas accidentales

  4. Limpiar recursos antes de salir es una buena práctica

  5. Mensaje de despedida mejora la experiencia de usuario


📝 Cuestionario de repaso

Pregunta 1

¿Qué función usamos para terminar el programa elegantemente?
a) stop()
b) end()
c) quit()
d) close()

Pregunta 2

¿Por qué es buena idea verificar múltiples frases como "salir", "adiós", etc.?
a) Para hacer el código más largo
b) Porque diferentes usuarios dicen cosas diferentes
c) Porque es obligatorio
d) Para confundir al asistente

Pregunta 3

¿Qué hace sys.exit(0) en comparación con sys.exit(1)?
a) Nada, son iguales
b) 0 es éxito, 1 es error
c) 0 es más rápido
d) 1 es para Windows, 0 para Mac

Pregunta 4

¿Por qué podríamos querer pedir confirmación antes de salir?
a) Para evitar salidas accidentales
b) Para hacer el programa más lento
c) Porque es divertido
d) Para practicar más código

Pregunta 5

¿Qué debemos hacer ANTES de llamar a quit()?
a) Nada, salir inmediatamente
b) Limpiar recursos (detener motor de voz, etc.)
c) Reinstalar Python
d) Esperar 10 segundos


Respuestas del cuestionario

  1. c) quit() - Aunque sys.exit() también es correcto

  2. b) Porque diferentes usuarios dicen cosas diferentes - Flexibilidad es clave en asistentes de voz

  3. b) 0 es éxito, 1 es error - Convención estándar en programación

  4. a) Para evitar salidas accidentales - Mejora la experiencia de usuario

  5. b) Limpiar recursos (detener motor de voz, etc.) - Evita problemas como audio que sigue sonando


🎁 Reto final: Mejora tu sistema de salida

Desafío 1: Historial de sesión

python

def guardar_historial_sesion():

    """Guarda lo que se hizo en la sesión"""

    with open("historial.txt", "a", encoding="utf-8") as f:

        f.write(f"Sesión: {time.strftime('%Y-%m-%d %H:%M')}\n")

        f.write(f"Comandos: {contador_comandos}\n")

        f.write("="*50 + "\n")

Desafío 2: Modo incógnito

python

def toggle_modo_incognito():

    """No guarda historial cuando está activo"""

    global modo_incognito

    modo_incognito = not modo_incognito

    hablar("Modo incógnito " + ("activado" if modo_incognito else "desactivado"))

Desafío 3: Reinicio en vez de salida

python

def reiniciar_asistente():

    """Reinicia el asistente sin cerrar el programa"""

    hablar("Reiniciando sistema...")

    # Reiniciar variables

    # Reconectar servicios

    # Mantener el loop principal

    hablar("Reinicio completo. ¡Hola de nuevo!")


🎉 ¡Felicidades!

Ahora tu asistente tiene:

  • ✅ Comando de salida elegante

  • ✅ Manejo de múltiples frases de despedida

  • ✅ Posibilidad de confirmación

  • ✅ Limpieza de recursos antes de salir

  • ✅ Código de salida profesional

Próximo paso: Agregar modo suspensión, historial de sesiones, o reinicio automático.


https://www.youtube.com/watch?v=Pj9KbAKpQyk

https://www.youtube.com/watch?v=-0tIy8wWtzE

https://www.youtube.com/watch?v=YqSSId7xfwU

https://www.youtube.com/watch?v=MjK-j7YJ5YI


https://www.youtube.com/watch?v=l2G8-iQYfoA



https://www.youtube.com/watch?v=t-YO0XeHczU


Comentarios

Entradas más populares de este blog

1-7. Transforma tu audio a texto

10. Haz que tu asistente hable

8. NUEVO - Solución si tu micrófono no está captando tu audio