Reto de python para crear un gestor de tareas en la consola
Capítulo 2: Gestor de tareas en consola con Python
Dificultad:
Requisitos para superar el reto
Crees que este reto es muy complicado o no lo sabes resolver? No te preocupes, haz este curso básico de Python y vuelve aquí:
A continuación, tienes un listado de todo lo que necesitas saber para afrontar el reto y superarlo.
- Variables
- Tipos de datos básicos
- Manejo básico de cadenas de caracteres
- Funciones print()
- Manejo básico de bucles
- Condicionales
- Operadores aritméticos
- Operadores lógicos
- Manejo de listas
- Funciones
Todo esto y mucho más, lo aprenderás en ese curso básico de Python.
Además, estos temas que no se han dado en el curso básico: (Te daré las indicaciones necesarias para que no sea un problema.)
- Manejo básico de módulos e importaciones
- Uso de la función predefinida
enumerate()
- Bucles con dos iteradores
Objetivo principal del ejercicio
El objetivo del ejercicio, es crear un programa de consola para gestionar tareas, con varias funcionalidades.
Para conseguir esto, no solo tendrás que saber la teórica de mi curso básico de Python, si no que también, deberás seguir ciertas instrucciones para programar con temas que no se han dado en ese curso.
La idea de hacer esto, es que vayas saliendo de tu zona de confort, y empieces a aprender sobre la marcha, a medida que practicas.
Primero te voy a indicar aquí los componentes que requiere esta aplicación, y a partir de ahí, ves consultando la solución hasta donde vayas necesitando. Ponte a prueba todo lo que quieras, o ves simplemente aprendiendo a medida que ves como se resuelve cada parte.
Componentes de la aplicación
El programa contará con dos módulos:
- app.py
- funciones.py
El primer módulo (app.py) contendrá la parte esencial de presentación para el usuario.
La interfaz de usuario la formará un bucle indeterminado (while True), con un menú.
El segundo módulo contendrá una lista para gestionar las tareas y cuatro funciones, que operarán toda la lógica de nuestra aplicación.
Estas son las funcionalidades que hay que crear:
- Añadir tarea
- Ver tareas
- Marcar tarea como completada
- Eliminar tarea
- Salir del programa
Crear los archivos para los módulos
Todavía no he explicado el tema de módulos en el curso básico, así que no te preocupes si no sabes sobre este tema, ya que te voy a explicar lo que haga falta.
Para crear un módulo de Python, tienes que crear un archivo con extensión .py.
Entonces, eso es lo que quiero que hagas. Crea estos dos archivos:
- app.py
- funciones.py
Ambos deberán estar en la raíz del proyecto. Sin carpetas.
app.py
Una vez creados los dos módulos, abre el módulo app.py. En él, escribe en la primera línea el siguiente fragmento:
from funciones import *
Esto es una importación. Con ella, tendrás acceso automático a todos los componentes del módulo importado, en este caso el de funciones.py.
Si ya manejas importaciones con Python, haz la importación de la forma que quieras. Por ejemplo así:
import funciones
Esta segunda forma es la que utilizaré en la resolución del proyecto.
Crear un menú para la interfaz de usuario
El siguiente paso es el de crear un menú para los usuarios. Este menú tendrá que tener las siguientes opciones:
- Título de tu aplicación
- 1. Añadir tarea
- 2. Ver tareas
- 3. Marcar tarea como completada
- 4. Eliminar tarea
- 5. Salir del programa
En un menú de consola es importante que marques de alguna forma las opciones, por ejemplo, con números, como puedes ver en este listado.
# Importación de la lógica
import funciones
# Bucle principal
while True:
print("\n***** --- Gestor de tareas de ConsoleTec --- ******\n ")
print("1. Añadir tarea")
print("2. Ver tareas")
print("3. Marcar tarea como completada")
print("4. Eliminar tarea")
print("5. Salir")
# Entrada para el usuario
opcion = input("Introduzca una opción: ")
print("\n")
# Menú de opciones
match opcion:
case "1":
pass
case "2":
pass
case "3":
pass
case "4":
pass
case "5":
pass
case _:
pass
El menú es simplemente un bucle indeterminado, que permite mediante una entrada, que el usuario elija opciones, hasta que decida salir.
Añadir la funcionalidad de salida y opción inválida
Lo siguiente que hay que hacer, es añadir la funcionalidad de salida del programa (opción 5). Para ello, avisa al usuario de que se está saliendo del programa, y utiliza uno de los elementos de Python para romper la ejecución del bucle.
También añade un mensaje que avise de que se introdujo una opción inválida, si no está contemplada en el condicional.
Esta sería una posible solución:
# Importación de la lógica
import funciones
# Bucle principal
while True:
print("\n***** --- Gestor de tareas de ConsoleTec --- ******\n ")
print("1. Añadir tarea")
print("2. Ver tareas")
print("3. Marcar tarea como completada")
print("4. Eliminar tarea")
print("5. Salir")
# Entrada para el usuario
opcion = input("Introduzca una opción: ")
print("\n")
# Menú de opciones
match opcion:
case "1":
pass
case "2":
pass
case "3":
pass
case "4":
pass
case "5":
print("Gracias por usar el software de ConsoleTec. Desconectando...")
break
case _:
print("Opción inválida.")
funciones.py
Vamos a crear la lógica de la aplicación. De momento, el esqueleto.
Primero añade una lista sobre la que ir guardando las tareas.
Después, añade las funciones.
Las cuatro funcionalidades que forman la lógica son estas:
- Añadir tarea
- Ver tareas
- Marcar tarea como completada
- Eliminar tarea
# Lista de tareas
tareas = []
# Funciones del programa
def agregar_tarea(lista):
pass
def ver_tareas(lista):
pass
def tarea_completada(lista):
pass
def eliminar_tarea(lista):
pass
Estas funciones tienen un único parámetro, que servirá para pasar la lista.
Enlazar la interfaz con la lógica
Ahora, volvemos al archivo app.py, a enlazar la interfaz con la parte lógica.
Para ello, solo tendrás que hacer llamadas a las funciones en los case
correspondientes.
Para llamar a los elementos del módulo, tendrás que poner de prefijo el nombre del módulo importado. Por ejemplo, para llamar a la función agregar_tarea()
del módulo funciones, lo hacemos con la sintaxis de modulo.función
. Aunque esto depende de como hayas hecho la importación. Si la has hecho como yo, esta es la forma.
# Importación de la lógica
import funciones
# Bucle principal
while True:
print("\n***** --- Gestor de tareas de ConsoleTec --- ******\n ")
print("1. Añadir tarea")
print("2. Ver tareas")
print("3. Marcar tarea como completada")
print("4. Eliminar tarea")
print("5. Salir")
# Entrada para el usuario
opcion = input("Introduzca una opción: ")
print("\n")
# Menú de opciones
match opcion:
case "1":
funciones.agregar_tarea(funciones.tareas)
case "2":
funciones.ver_tareas(funciones.tareas)
case "3":
funciones.tarea_completada(funciones.tareas)
case "4":
funciones.eliminar_tarea(funciones.tareas)
case "5":
print("Gracias por usar el software de ConsoleTec. Desconectando...")
break
case _:
print("Opción inválida.")
Completar la lógica
Una vez está enlazada la interfaz con la lógica, es el momento de ir completando cada una de las funciones.
Función agregar_tarea()
Esta función servirá para añadir nuevas tareas. Debes completar todos los pasos que puedas. Hazlos de la forma que creas conveniente. No tiene porqué ser igual que mi solución.
# Funciones del programa
def agregar_tarea(lista):
# Entrada para la tarea
# Añadir la tarea al final de la lista
# Informe de tarea añadida
# Imprime la tarea añadida
# Informa del número de tarea
def agregar_tarea(lista):
# Entrada para la tarea
tarea = input("Introduzca la descripción de la tarea: ")
# Añadir la tarea al final de la lista
lista.append(tarea)
# Informe de tarea añadida
print("\nLa tarea se añadió a la lista de tareas pendientes.\n")
# Imprime la tarea añadida
print("La tarea añadadida es esta:")
print(f"{tarea}")
# Informa del número de tarea
print(f"La tarea se almacenó en la posición {len(lista)}\n")
- Línea 1:
def agregar_tarea(lista):
- Se define la función
agregar_tarea()
, con un parámetro.
- Se define la función
- Línea 3:
tarea = input("Introduzca la descripción de la tarea: ")
- Entrada de datos para el usuario. En ella, podrá introducir un
str
con la tarea.
- Entrada de datos para el usuario. En ella, podrá introducir un
- Línea 6:
lista.append(tarea)
- Esta línea añade la tarea que el usuario acaba de introducir al final de la
lista
.append()
es un método de las listas de Python que añade un elemento al final de la lista.
La tarea que se almacena es elstr
de la variabletarea
, pasado como argumento paraappend()
.
- Esta línea añade la tarea que el usuario acaba de introducir al final de la
- Líneas 9, 12, 14 y 17:
- Se informa al usuario de que la tarea se ha añadido, cuál es la tarea añadida, e informa de la posición del elemento en la lista, gracias a la función
len()
, que permite contar el total de elementos que tiene la lista.
Puesto que los elementos se añaden siempre al final de la lista, siempre coincide el número de tarea añadida, con el número total de elementos de la lista.
- Se informa al usuario de que la tarea se ha añadido, cuál es la tarea añadida, e informa de la posición del elemento en la lista, gracias a la función
Función ver_tareas()
Esta función servirá para añadir nuevas tareas:
def ver_tareas(lista):
# Condicional que evalúe si algo está en la lista
# Si hay algo en la lista se presenta
# Si la lista está vacía avisa de ello
# Mensaje de fin de listado
Para resolver esto, puedes utilizar un condicional, un bucle con doble iterador y una llamada a la función predefinida enumerate().
La función enumerate de Python
Por si no conoces la función enumerate()
de Python, te la explico en un momento.
Esta función devuelve un objeto iterador. Este objeto se puede iterar con un bucle, pero para saber como, debes conocer con que datos trabaja.
Si utilizamos un bucle simple, con un iterador, veremos lo que maneja enumerate()
en cada iteración:
tareas = ["Tarea A", "Tarea B", "Tarea C"]
for tarea in enumerate(tareas):
print(tarea)
(0, 'Tarea A')
(1, ' Tarea B')
(2, 'Tarea C')
La función hace una enumeración desde el 0, hasta la última posición de la lista. Esta enumeración, la almacena en tuplas de pares de posición/valor.
Si quieres hacer un listado con los elementos de la lista, solo tienes que iterar primero la posición de número y luego, la de la tarea.
Para que quede un listado como este:
- Tarea A
- Tarea B
- Tarea C
Esto lo puedes hacer con un bucle con doble iterador:
tareas = ["Tarea A", "Tarea B", "Tarea C"]
for indice, tarea in enumerate(tareas):
print(indice, tarea)
0 Tarea A
1 Tarea B
2 Tarea C
El primer iterador (indice
) itera la primera posición de cada tupla producida por el enumerate()
. El segundo, el valor.
Con estos dos iteradores podemos presentar el listado como queramos.
Así no necesitamos utilizar un bucle anidado, y obtenemos dos datos de una iteración del bucle.
Deberás ingeniártelas para que el contador de la lista empiece en 1, y no en 0.
def ver_tareas(lista):
# Condicional que evalúe si algo está en la lista
# Si hay algo en la lista se presenta
if lista:
for indice, tarea in enumerate(lista):
print(f"{indice + 1}. {tarea}")
# Si la lista está vacía avisa de ello
else:
print("No hay tareas pendientes.")
# Mensaje de fin de listado
print("--- FIN DEL LISTADO DE TAREAS ---")
- Línea 1:
def ver_tareas(lista):
- Esta línea define una función llamada
ver_tareas
que toma un argumento llamadolista
.
- Esta línea define una función llamada
- Línea 4:
if lista:
- Esta línea es una declaración condicional que verifica si la
lista
contiene algún elemento. Si lalista
no está vacía, el código dentro de este bloqueif
se ejecutará.
- Esta línea es una declaración condicional que verifica si la
- Línea 5:
for indice, tarea in enumerate(lista):
- Esta línea es un bucle
for
que recorre cada elemento en lalista
. La funciónenumerate()
devuelve tanto el índice (posición) como el valor de cada elemento en lalista
. Los valores de índice y elemento se almacenan en las variablesindice
ytarea
, respectivamente.
- Esta línea es un bucle
- Línea 6:
print(f"{indice + 1}. {tarea}")
- Esta línea imprime el número de la tarea (que es el índice más uno, para hacer que la numeración comience en 1 en lugar de 0) y la tarea misma.
- Línea 8:
else:
- Esta línea corresponde al bloque
else
del condicionalif
. Este bloque se ejecutará si lalista
está vacía.
- Esta línea corresponde al bloque
- Línea 9:
print("No hay tareas pendientes.")
- Esta línea imprime un mensaje que indica que no hay tareas pendientes.
- Línea 12:
print("--- FIN DEL LISTADO DE TAREAS ---")
- Esta línea imprime un mensaje que indica el fin del listado de tareas. Este mensaje se imprime independientemente de si la
lista
estaba vacía o no.
- Esta línea imprime un mensaje que indica el fin del listado de tareas. Este mensaje se imprime independientemente de si la
Función tarea_completada()
Esta función servirá para marcar las tareas existentes en la lista, por parte del usuario.
Lo primero que hará, será desplegar el listado de tareas. Para ello. Utiliza una función ya existente en el programa. Así, el usuario no irá escogiendo una opción a ciegas.
Quedará algo así:
1. Tarea A
2. Tarea B
3. Tarea C
--- FIN DEL LISTADO DE TAREAS ---
Una vez que haya obtenido el listado de tareas, podrá introducir con una entrada, un número de opción.
Introduzca el número de la tarea a marcar como completada:
Un condicional evaluará si la opción existe en el listado, o no.
Si la opción no existe, se le avisa de ello.
Introduzca el número de la tarea a marcar como completada: 5
Opción inválida.
En cambio, si existe, utilizaremos un segundo condicional anidado.
El condicional anidado evaluará si la opción ya está marcada como completada, o no. Si ya lo está, avisa al usuario de ello. En cambio, si no lo está, deberá marcarla.
Te dejo una serie de comentarios para que tengas una guía de los pasos a completar. No obstante, lo puedes hacer como quieras. Esto es solo para que te orientes.
def tarea_completada(lista):
# Llamamos a la función ver_tareas()
# Entrada para que el usuario introduzca una tarea
# Condicional para marcar tareas como completadas
# Condicional para evaluar si la tarea ya estaba completada
# Si la tarea ya está en la lista...
# En cambio, si no está...
# Avisar si la opción elegida es inválida
def tarea_completada(lista):
# Llamamos a la función ver_tareas()
ver_tareas(lista)
# Entrada para que el usuario introduzca una tarea
completada = int(input("Introduzca el número de la tarea a marcar como completada: "))
# Condicional para marcar tareas como completadas
if completada > 0 and completada <= len(lista):
# Condicional para evaluar si la tarea ya estaba completada
# Si la tarea ya está en la lista...
if "(Completada)" in lista[completada - 1]:
print("La tarea ya estaba marcada como completada.")
# En cambio, si no está...
else:
lista[completada - 1] = "(Completada) " + lista[completada - 1]
print("Se marcó la tarea como completada.")
# Avisar si la opción elegida es inválida
else:
print("Opción inválida.")
- Línea 1:
def tarea_completada(lista):
- Esta línea define una función llamada
tarea_completada
que toma un parámetrolista
.
- Esta línea define una función llamada
- Línea 3:
ver_tareas(lista)
- Esta línea llama a la función
ver_tareas
conlista
como argumento.
- Esta línea llama a la función
- Línea 6:
completada = int(input("Introduzca el número de la tarea a marcar como completada: "))
- Esta línea solicita al usuario que introduzca el número de la tarea a marcar como completada y lo almacena en la variable
completada
.
- Esta línea solicita al usuario que introduzca el número de la tarea a marcar como completada y lo almacena en la variable
- Línea 9:
if completada > 0 and completada <= len(lista):
- Esta línea verifica si el número de tarea introducido es válido. Es decir, si está dentro del rango de la lista de tareas.
- Línea 12:
if "(Completada)" in lista[completada - 1]:
- Esta línea verifica si la tarea seleccionada ya está marcada como completada.
- Línea 13:
print("La tarea ya estaba marcada como completada.")
- Si la tarea ya estaba completada, esta línea imprime un mensaje informando al usuario de ello.
- Línea 16:
lista[completada - 1] = "(Completada) " + lista[completada - 1]
- Si la tarea no estaba completada, esta línea marca la tarea como completada añadiendo '(Completada)' al principio de la tarea en la lista.
- Línea 17:
print("Se marcó la tarea como completada.")
- Esta línea imprime un mensaje informando al usuario de que la tarea ha sido marcada como completada.
- Línea 20:
print("Opción inválida.")
- Si el número de tarea ingresado no es válido, esta línea imprime un mensaje informando al usuario de que la opción es inválida.
Función eliminar_tarea()
Esta función servirá para eliminar tareas pendientes. Aquí tienes las partes que tienes que completar:
def eliminar_tarea(lista):
#Llamamos a la función ver_tareas()
# Entrada para que el usuario introduzca una tarea
# Opción inválida si la tarea no está en el rango de la lista
# Si la opción es válida se elimina la tarea
# Si la lista está vacía se avisa de ello
Estos comentarios te dan una perspectiva de como completar esta funcionalidad, pero hazla de la forma que quieras. No tiene porqué seguir esta estructura.
def eliminar_tarea(lista):
if lista:
#Llamamos a la función ver_tareas()
ver_tareas(lista)
# Entrada para que el usuario introduzca una tarea
tarea = int(input("Introduzca el número de la tarea a eliminar: "))
# Opción inválida si la tarea no está en el rango de la lista
if tarea <= 0 or tarea > len(lista):
print("Opción inválida.")
# Si la opción es válida se elimina la tarea
else:
del lista[tarea - 1]
print("Se eliminó la tarea.")
# Si la lista está vacía se avisa de ello
else:
print("No hay tareas.")
- Línea 1:
def eliminar_tarea(lista):
- Esta línea define una función llamada
eliminar_tarea
que toma un argumento llamadolista
.
- Esta línea define una función llamada
- Línea 3:
if lista:
- Esta línea evalúa si
lista
no está vacía. Silista
contiene elementos, la condición es verdadera y se ejecuta el bloque de código dentro delif
.
- Esta línea evalúa si
- Línea 5:
ver_tareas(tareas)
- Esta línea llama a la función llamada
ver_tareas()
y le pasalista
como argumento.
- Esta línea llama a la función llamada
- Línea 8:
tarea = int(input("Introduzca el número de la tarea a eliminar: "))
- Esta línea solicita al usuario que introduzca un número y convierte la entrada en un entero utilizando
int()
. Este número se almacena en la variabletarea
.
- Esta línea solicita al usuario que introduzca un número y convierte la entrada en un entero utilizando
- Línea 11:
if tarea <= 0 or tarea > len(lista):
- Esta línea verifica si el número introducido por el usuario es menor o igual a 0, o mayor que la longitud de
lista
. Si cualquiera de estas condiciones es verdadera, la opción es inválida.
- Esta línea verifica si el número introducido por el usuario es menor o igual a 0, o mayor que la longitud de
- Línea 12:
print("Opción inválida.")
- Si la condición en la línea anterior es verdadera, se imprime el mensaje "Opción inválida.".
- Línea 15:
else:
- Este
else
se ejecuta si la condición en la línea 11 es falsa, es decir, si el número introducido es válido.
- Este
- Línea 16:
del lista[tarea - 1]
- Esta línea elimina el elemento en la posición
tarea - 1
delista
. Se usatarea - 1
porque las listas en Python son indexadas desde cero.
- Esta línea elimina el elemento en la posición
- Línea 17:
print("Se eliminó la tarea.")
- Después de eliminar la tarea, se imprime el mensaje "Se eliminó la tarea.".
- Línea 20:
else:
- Este
else
se empareja con elif
en la línea 3 y se ejecuta silista
está vacía.
- Este
- Línea 21:
print("No hay tareas.")
- Si
lista
está vacía, se imprime el mensaje "No hay tareas.".
- Si
Comentarios
Si te quedan dudas sobre el temario, sobre Programación, Python o cualquier otra cosa relacionada o simplemente quieres agradecer, aquí tienes tu sitio para dejar tu granito de arena. Gracias por tus comentarios y por darle vida a este sitio web.