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:
Experiencia de usuario: Es más natural decir "adiós" que cerrar la ventana
Limpieza: Permite cerrar recursos adecuadamente
Seguridad: Evita procesos colgados en segundo plano
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
quit() o sys.exit() terminan el programa
Verificar múltiples frases para mayor flexibilidad
Confirmación opcional evita salidas accidentales
Limpiar recursos antes de salir es una buena práctica
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
c) quit() - Aunque sys.exit() también es correcto
b) Porque diferentes usuarios dicen cosas diferentes - Flexibilidad es clave en asistentes de voz
b) 0 es éxito, 1 es error - Convención estándar en programación
a) Para evitar salidas accidentales - Mejora la experiencia de usuario
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
Publicar un comentario