Curso Python #10: Proyecto Final - Gestor de Tareas
Proyecto Final: Gestor de Tareas en la Terminal - Parte 10 de 10

¡Llegamos al ultimo articulo del Curso de Python desde Cero! Este es el articulo 10 de 10, y es el momento de poner en practica todo lo que has aprendido a lo largo del curso.
Vamos a construir un gestor de tareas (to-do list) que funciona en la terminal. Este proyecto usa variables, funciones, listas, diccionarios, programacion orientada a objetos (POO), manejo de archivos y manejo de errores — basicamente todo lo que hemos cubierto.
Al final tendras un programa completo y funcional que puedes usar en tu dia a dia y que demuestra que ya sabes programar en Python.
Descripcion del proyecto
Nuestro gestor de tareas tendra las siguientes funcionalidades:
- Agregar tareas con titulo y descripcion
- Listar todas las tareas mostrando su estado (pendiente o completada)
- Marcar tareas como completadas
- Eliminar tareas
- Buscar tareas por palabra clave
- Guardar las tareas en un archivo JSON para que no se pierdan al cerrar el programa
- Menu interactivo con opciones numeradas
El proyecto tendra 3 archivos:
| Archivo | Que contiene |
|---|---|
models.py |
La clase Task (modelo de datos) |
task_manager.py |
La clase TaskManager (logica de negocio) |
main.py |
El menu interactivo (interfaz de usuario) |
Paso 1: Estructura del proyecto
Primero, crea una carpeta para el proyecto y dentro de ella los tres archivos:
1# Estructura de carpetas
2gestor_tareas/
3 models.py
4 task_manager.py
5 main.py
Puedes crear la carpeta y los archivos desde la terminal:
1# En la terminal (no es codigo Python, son comandos)
2# Windows:
3mkdir gestor_tareas
4cd gestor_tareas
5type nul > models.py
6type nul > task_manager.py
7type nul > main.py
8
9# macOS / Linux:
10mkdir gestor_tareas
11cd gestor_tareas
12touch models.py task_manager.py main.py
Paso 2: Modelo de datos — La clase Task
Empecemos por el modelo de datos. La clase Task representa una tarea individual con sus propiedades.
Abre el archivo models.py y escribe:
1from datetime import datetime
2
3
4class Task:
5 """Representa una tarea individual en el gestor."""
6
7 def __init__(self, task_id, title, description=""):
8 self.task_id = task_id
9 self.title = title
10 self.description = description
11 self.completed = False
12 self.created_at = datetime.now().strftime("%Y-%m-%d %H:%M")
13
14 def mark_completed(self):
15 """Marca la tarea como completada."""
16 self.completed = True
17
18 def to_dict(self):
19 """Convierte la tarea a diccionario (para guardar en JSON)."""
20 return {
21 "task_id": self.task_id,
22 "title": self.title,
23 "description": self.description,
24 "completed": self.completed,
25 "created_at": self.created_at
26 }
27
28 @classmethod
29 def from_dict(cls, data):
30 """Crea una tarea desde un diccionario (para cargar desde JSON)."""
31 task = cls(data["task_id"], data["title"], data.get("description", ""))
32 task.completed = data.get("completed", False)
33 task.created_at = data.get("created_at", "")
34 return task
35
36 def __str__(self):
37 """Representacion en texto de la tarea."""
38 status = "✓" if self.completed else "○"
39 text = f"[{status}] #{self.task_id} - {self.title}"
40 if self.description:
41 text += f"
42 {self.description}"
43 text += f"
44 Creada: {self.created_at}"
45 return text
Veamos que hace cada parte:
__init__: Inicializa la tarea con un ID, titulo, descripcion (opcional), estado (pendiente por defecto) y fecha de creacionmark_completed: Cambia el estado a completadato_dict: Convierte la tarea a un diccionario para poder guardarla en un archivo JSONfrom_dict: Metodo de clase que crea una tarea desde un diccionario (para cargar datos desde JSON)__str__: Define como se muestra la tarea cuando la imprimimos conprint()
Paso 3: Logica de negocio — La clase TaskManager
Ahora vamos a crear la clase que maneja todas las operaciones: agregar, listar, completar, eliminar y buscar tareas. Tambien se encarga de guardar y cargar las tareas desde un archivo JSON.
Abre el archivo task_manager.py y escribe:
1import json
2import os
3from models import Task
4
5
6class TaskManager:
7 """Gestiona la lista de tareas con persistencia en archivo JSON."""
8
9 def __init__(self, filename="tasks.json"):
10 self.filename = filename
11 self.tasks = []
12 self.next_id = 1
13 self.load_tasks()
14
15 def load_tasks(self):
16 """Carga las tareas desde el archivo JSON."""
17 if not os.path.exists(self.filename):
18 return
19
20 try:
21 with open(self.filename, "r", encoding="utf-8") as file:
22 data = json.load(file)
23 self.tasks = [Task.from_dict(item) for item in data]
24 if self.tasks:
25 self.next_id = max(t.task_id for t in self.tasks) + 1
26 print(f"Se cargaron {len(self.tasks)} tareas desde {self.filename}")
27 except (json.JSONDecodeError, KeyError) as e:
28 print(f"Error al leer el archivo de tareas: {e}")
29 print("Se iniciara con una lista vacia.")
30 self.tasks = []
31
32 def save_tasks(self):
33 """Guarda las tareas en el archivo JSON."""
34 try:
35 data = [task.to_dict() for task in self.tasks]
36 with open(self.filename, "w", encoding="utf-8") as file:
37 json.dump(data, file, indent=2, ensure_ascii=False)
38 except IOError as e:
39 print(f"Error al guardar las tareas: {e}")
40
41 def add_task(self, title, description=""):
42 """Agrega una nueva tarea a la lista."""
43 if not title or not title.strip():
44 raise ValueError("El titulo de la tarea no puede estar vacio")
45
46 task = Task(self.next_id, title.strip(), description.strip())
47 self.tasks.append(task)
48 self.next_id += 1
49 self.save_tasks()
50 return task
51
52 def list_tasks(self, show_all=True):
53 """Retorna las tareas (todas o solo pendientes)."""
54 if show_all:
55 return self.tasks
56 return [t for t in self.tasks if not t.completed]
57
58 def complete_task(self, task_id):
59 """Marca una tarea como completada."""
60 task = self._find_task(task_id)
61 if task is None:
62 raise ValueError(f"No existe una tarea con ID #{task_id}")
63 if task.completed:
64 raise ValueError(f"La tarea #{task_id} ya esta completada")
65
66 task.mark_completed()
67 self.save_tasks()
68 return task
69
70 def delete_task(self, task_id):
71 """Elimina una tarea de la lista."""
72 task = self._find_task(task_id)
73 if task is None:
74 raise ValueError(f"No existe una tarea con ID #{task_id}")
75
76 self.tasks.remove(task)
77 self.save_tasks()
78 return task
79
80 def search_tasks(self, keyword):
81 """Busca tareas que contengan la palabra clave en titulo o descripcion."""
82 if not keyword or not keyword.strip():
83 raise ValueError("La palabra de busqueda no puede estar vacia")
84
85 keyword = keyword.lower().strip()
86 results = [
87 t for t in self.tasks
88 if keyword in t.title.lower() or keyword in t.description.lower()
89 ]
90 return results
91
92 def get_stats(self):
93 """Retorna estadisticas de las tareas."""
94 total = len(self.tasks)
95 completed = sum(1 for t in self.tasks if t.completed)
96 pending = total - completed
97 return {
98 "total": total,
99 "completed": completed,
100 "pending": pending
101 }
102
103 def _find_task(self, task_id):
104 """Busca una tarea por su ID (metodo privado)."""
105 for task in self.tasks:
106 if task.task_id == task_id:
107 return task
108 return None
Esta clase tiene toda la logica del gestor de tareas:
load_tasksysave_tasks: Manejan la persistencia en JSON (Parte 8 del curso)add_task: Valida y agrega una tarea nuevalist_tasks: Puede mostrar todas o solo las pendientes (listas por comprension, Parte 4)complete_taskydelete_task: Buscan la tarea y lanzan errores si no existe (Parte 9)search_tasks: Busca por palabra clave en titulo y descripcionget_stats: Retorna estadisticas usando diccionarios (Parte 5)_find_task: Metodo privado auxiliar para buscar por ID
_find_task empieza con guion bajo (_). En Python, esto indica que es un metodo "privado" — solo debe usarse dentro de la clase, no desde fuera.
Paso 4: Guardar y cargar tareas con JSON
La persistencia es lo que hace que las tareas no se pierdan cuando cierras el programa. Cada vez que agregas, completas o eliminas una tarea, el programa guarda automaticamente todo en un archivo tasks.json.
Asi se ve el archivo JSON que genera el programa:
1# Contenido de tasks.json (generado automaticamente)
2[
3 {
4 "task_id": 1,
5 "title": "Comprar leche",
6 "description": "De la tienda de la esquina",
7 "completed": false,
8 "created_at": "2025-01-15 10:30"
9 },
10 {
11 "task_id": 2,
12 "title": "Estudiar Python",
13 "description": "Terminar el proyecto final del curso",
14 "completed": true,
15 "created_at": "2025-01-15 10:35"
16 }
17]
El flujo funciona asi:
- Cuando el programa inicia,
load_tasks()lee el archivo JSON y crea objetosTask - Cuando haces cualquier cambio,
save_tasks()convierte todas las tareas a diccionarios y las guarda en JSON - Si el archivo no existe (primera vez), el programa empieza con una lista vacia
- Si el archivo esta corrupto, el programa muestra un error y empieza con lista vacia en vez de romperse
ensure_ascii=False en json.dump() para que los caracteres especiales (como acentos) se guarden correctamente en el archivo.
Paso 5: Menu interactivo — El archivo main.py
Finalmente, vamos a crear la interfaz de usuario: un menu interactivo que le permite al usuario elegir que quiere hacer.
Abre el archivo main.py y escribe:
1from task_manager import TaskManager
2
3
4def show_menu():
5 """Muestra el menu principal."""
6 print()
7 print("=" * 45)
8 print(" GESTOR DE TAREAS - Menu Principal")
9 print("=" * 45)
10 print(" 1. Agregar tarea")
11 print(" 2. Listar todas las tareas")
12 print(" 3. Listar tareas pendientes")
13 print(" 4. Completar una tarea")
14 print(" 5. Eliminar una tarea")
15 print(" 6. Buscar tareas")
16 print(" 7. Ver estadisticas")
17 print(" 0. Salir")
18 print("-" * 45)
19
20
21def add_task_flow(manager):
22 """Flujo para agregar una tarea."""
23 print("
24--- Agregar Nueva Tarea ---")
25 title = input("Titulo: ").strip()
26 if not title:
27 print("Error: el titulo no puede estar vacio.")
28 return
29
30 description = input("Descripcion (opcional, presiona Enter para omitir): ").strip()
31
32 try:
33 task = manager.add_task(title, description)
34 print(f"
35Tarea agregada exitosamente:")
36 print(task)
37 except ValueError as e:
38 print(f"Error: {e}")
39
40
41def list_tasks_flow(manager, show_all=True):
42 """Flujo para listar tareas."""
43 label = "Todas las Tareas" if show_all else "Tareas Pendientes"
44 print(f"
45--- {label} ---")
46
47 tasks = manager.list_tasks(show_all=show_all)
48 if not tasks:
49 print("No hay tareas para mostrar.")
50 return
51
52 for task in tasks:
53 print()
54 print(task)
55 print(f"
56Total: {len(tasks)} tarea(s)")
57
58
59def complete_task_flow(manager):
60 """Flujo para completar una tarea."""
61 print("
62--- Completar Tarea ---")
63 list_tasks_flow(manager, show_all=False)
64
65 try:
66 task_id = int(input("
67Ingresa el ID de la tarea a completar: "))
68 task = manager.complete_task(task_id)
69 print(f"
70Tarea completada:")
71 print(task)
72 except ValueError as e:
73 print(f"Error: {e}")
74
75
76def delete_task_flow(manager):
77 """Flujo para eliminar una tarea."""
78 print("
79--- Eliminar Tarea ---")
80 list_tasks_flow(manager)
81
82 try:
83 task_id = int(input("
84Ingresa el ID de la tarea a eliminar: "))
85 confirm = input(f"¿Seguro que quieres eliminar la tarea #{task_id}? (s/n): ")
86 if confirm.lower() == "s":
87 task = manager.delete_task(task_id)
88 print(f"
89Tarea eliminada: {task.title}")
90 else:
91 print("Operacion cancelada.")
92 except ValueError as e:
93 print(f"Error: {e}")
94
95
96def search_tasks_flow(manager):
97 """Flujo para buscar tareas."""
98 print("
99--- Buscar Tareas ---")
100 keyword = input("Palabra a buscar: ").strip()
101
102 try:
103 results = manager.search_tasks(keyword)
104 if not results:
105 print(f"No se encontraron tareas con '{keyword}'.")
106 return
107
108 print(f"
109Resultados para '{keyword}': {len(results)} tarea(s)")
110 for task in results:
111 print()
112 print(task)
113 except ValueError as e:
114 print(f"Error: {e}")
115
116
117def stats_flow(manager):
118 """Flujo para mostrar estadisticas."""
119 print("
120--- Estadisticas ---")
121 stats = manager.get_stats()
122
123 print(f" Total de tareas: {stats['total']}")
124 print(f" Completadas: {stats['completed']}")
125 print(f" Pendientes: {stats['pending']}")
126
127 if stats["total"] > 0:
128 percentage = (stats["completed"] / stats["total"]) * 100
129 bar_length = 20
130 filled = int(bar_length * stats["completed"] / stats["total"])
131 bar = "█" * filled + "░" * (bar_length - filled)
132 print(f" Progreso: [{bar}] {percentage:.0f}%")
133
134
135def main():
136 """Funcion principal del programa."""
137 print("
138Bienvenido al Gestor de Tareas")
139 manager = TaskManager()
140
141 while True:
142 show_menu()
143 option = input("Elige una opcion: ").strip()
144
145 if option == "1":
146 add_task_flow(manager)
147 elif option == "2":
148 list_tasks_flow(manager, show_all=True)
149 elif option == "3":
150 list_tasks_flow(manager, show_all=False)
151 elif option == "4":
152 complete_task_flow(manager)
153 elif option == "5":
154 delete_task_flow(manager)
155 elif option == "6":
156 search_tasks_flow(manager)
157 elif option == "7":
158 stats_flow(manager)
159 elif option == "0":
160 print("
161¡Hasta luego! Tus tareas estan guardadas.")
162 break
163 else:
164 print("Opcion no valida. Elige un numero del 0 al 7.")
165
166
167if __name__ == "__main__":
168 main()
El archivo main.py es la interfaz de usuario. Cada opcion del menu tiene su propia funcion (add_task_flow, complete_task_flow, etc.) que maneja la interaccion con el usuario y llama a los metodos de TaskManager.
Paso 6: Manejo de errores en todo el proyecto
Observa como el manejo de errores esta integrado en todo el proyecto:
En el modelo (models.py)
- El metodo
from_dictusa.get()con valores por defecto para evitarKeyError
En la logica (task_manager.py)
load_tasks: Atrapajson.JSONDecodeErrorsi el archivo esta corruptosave_tasks: AtrapaIOErrorsi no se puede escribir el archivoadd_task: Valida que el titulo no este vaciocomplete_task: Verifica que la tarea exista y no este ya completadadelete_task: Verifica que la tarea exista antes de eliminarsearch_tasks: Valida que la palabra clave no este vacia
En la interfaz (main.py)
- Cada flujo usa
try/exceptpara atrapar errores de validacion y mostrar mensajes amigables - La funcion
delete_task_flowpide confirmacion antes de eliminar - El menu principal maneja opciones invalidas con un mensaje claro
1# Ejemplo de como se ven los errores para el usuario:
2
3# Si intenta completar una tarea que no existe:
4# "Error: No existe una tarea con ID #99"
5
6# Si intenta agregar una tarea sin titulo:
7# "Error: el titulo no puede estar vacio."
8
9# Si escribe letras donde se espera un numero:
10# "Error: invalid literal for int() with base 10: 'abc'"
Codigo completo del proyecto
Aqui tienes el codigo completo de cada archivo para que puedas copiarlo y ejecutarlo directamente:
Archivo: models.py
1from datetime import datetime
2
3
4class Task:
5 """Representa una tarea individual en el gestor."""
6
7 def __init__(self, task_id, title, description=""):
8 self.task_id = task_id
9 self.title = title
10 self.description = description
11 self.completed = False
12 self.created_at = datetime.now().strftime("%Y-%m-%d %H:%M")
13
14 def mark_completed(self):
15 """Marca la tarea como completada."""
16 self.completed = True
17
18 def to_dict(self):
19 """Convierte la tarea a diccionario (para guardar en JSON)."""
20 return {
21 "task_id": self.task_id,
22 "title": self.title,
23 "description": self.description,
24 "completed": self.completed,
25 "created_at": self.created_at
26 }
27
28 @classmethod
29 def from_dict(cls, data):
30 """Crea una tarea desde un diccionario (para cargar desde JSON)."""
31 task = cls(data["task_id"], data["title"], data.get("description", ""))
32 task.completed = data.get("completed", False)
33 task.created_at = data.get("created_at", "")
34 return task
35
36 def __str__(self):
37 """Representacion en texto de la tarea."""
38 status = "✓" if self.completed else "○"
39 text = f"[{status}] #{self.task_id} - {self.title}"
40 if self.description:
41 text += f"\n {self.description}"
42 text += f"\n Creada: {self.created_at}"
43 return text
Archivo: task_manager.py
1import json
2import os
3from models import Task
4
5
6class TaskManager:
7 """Gestiona la lista de tareas con persistencia en archivo JSON."""
8
9 def __init__(self, filename="tasks.json"):
10 self.filename = filename
11 self.tasks = []
12 self.next_id = 1
13 self.load_tasks()
14
15 def load_tasks(self):
16 """Carga las tareas desde el archivo JSON."""
17 if not os.path.exists(self.filename):
18 return
19
20 try:
21 with open(self.filename, "r", encoding="utf-8") as file:
22 data = json.load(file)
23 self.tasks = [Task.from_dict(item) for item in data]
24 if self.tasks:
25 self.next_id = max(t.task_id for t in self.tasks) + 1
26 print(f"Se cargaron {len(self.tasks)} tareas desde {self.filename}")
27 except (json.JSONDecodeError, KeyError) as e:
28 print(f"Error al leer el archivo de tareas: {e}")
29 print("Se iniciara con una lista vacia.")
30 self.tasks = []
31
32 def save_tasks(self):
33 """Guarda las tareas en el archivo JSON."""
34 try:
35 data = [task.to_dict() for task in self.tasks]
36 with open(self.filename, "w", encoding="utf-8") as file:
37 json.dump(data, file, indent=2, ensure_ascii=False)
38 except IOError as e:
39 print(f"Error al guardar las tareas: {e}")
40
41 def add_task(self, title, description=""):
42 """Agrega una nueva tarea a la lista."""
43 if not title or not title.strip():
44 raise ValueError("El titulo de la tarea no puede estar vacio")
45
46 task = Task(self.next_id, title.strip(), description.strip())
47 self.tasks.append(task)
48 self.next_id += 1
49 self.save_tasks()
50 return task
51
52 def list_tasks(self, show_all=True):
53 """Retorna las tareas (todas o solo pendientes)."""
54 if show_all:
55 return self.tasks
56 return [t for t in self.tasks if not t.completed]
57
58 def complete_task(self, task_id):
59 """Marca una tarea como completada."""
60 task = self._find_task(task_id)
61 if task is None:
62 raise ValueError(f"No existe una tarea con ID #{task_id}")
63 if task.completed:
64 raise ValueError(f"La tarea #{task_id} ya esta completada")
65
66 task.mark_completed()
67 self.save_tasks()
68 return task
69
70 def delete_task(self, task_id):
71 """Elimina una tarea de la lista."""
72 task = self._find_task(task_id)
73 if task is None:
74 raise ValueError(f"No existe una tarea con ID #{task_id}")
75
76 self.tasks.remove(task)
77 self.save_tasks()
78 return task
79
80 def search_tasks(self, keyword):
81 """Busca tareas que contengan la palabra clave."""
82 if not keyword or not keyword.strip():
83 raise ValueError("La palabra de busqueda no puede estar vacia")
84
85 keyword = keyword.lower().strip()
86 results = [
87 t for t in self.tasks
88 if keyword in t.title.lower() or keyword in t.description.lower()
89 ]
90 return results
91
92 def get_stats(self):
93 """Retorna estadisticas de las tareas."""
94 total = len(self.tasks)
95 completed = sum(1 for t in self.tasks if t.completed)
96 pending = total - completed
97 return {"total": total, "completed": completed, "pending": pending}
98
99 def _find_task(self, task_id):
100 """Busca una tarea por su ID (metodo privado)."""
101 for task in self.tasks:
102 if task.task_id == task_id:
103 return task
104 return None
Archivo: main.py
1from task_manager import TaskManager
2
3
4def show_menu():
5 """Muestra el menu principal."""
6 print()
7 print("=" * 45)
8 print(" GESTOR DE TAREAS - Menu Principal")
9 print("=" * 45)
10 print(" 1. Agregar tarea")
11 print(" 2. Listar todas las tareas")
12 print(" 3. Listar tareas pendientes")
13 print(" 4. Completar una tarea")
14 print(" 5. Eliminar una tarea")
15 print(" 6. Buscar tareas")
16 print(" 7. Ver estadisticas")
17 print(" 0. Salir")
18 print("-" * 45)
19
20
21def add_task_flow(manager):
22 """Flujo para agregar una tarea."""
23 print("\n--- Agregar Nueva Tarea ---")
24 title = input("Titulo: ").strip()
25 if not title:
26 print("Error: el titulo no puede estar vacio.")
27 return
28
29 description = input("Descripcion (opcional, presiona Enter para omitir): ").strip()
30
31 try:
32 task = manager.add_task(title, description)
33 print(f"\nTarea agregada exitosamente:")
34 print(task)
35 except ValueError as e:
36 print(f"Error: {e}")
37
38
39def list_tasks_flow(manager, show_all=True):
40 """Flujo para listar tareas."""
41 label = "Todas las Tareas" if show_all else "Tareas Pendientes"
42 print(f"\n--- {label} ---")
43
44 tasks = manager.list_tasks(show_all=show_all)
45 if not tasks:
46 print("No hay tareas para mostrar.")
47 return
48
49 for task in tasks:
50 print()
51 print(task)
52 print(f"\nTotal: {len(tasks)} tarea(s)")
53
54
55def complete_task_flow(manager):
56 """Flujo para completar una tarea."""
57 print("\n--- Completar Tarea ---")
58 list_tasks_flow(manager, show_all=False)
59
60 try:
61 task_id = int(input("\nIngresa el ID de la tarea a completar: "))
62 task = manager.complete_task(task_id)
63 print(f"\nTarea completada:")
64 print(task)
65 except ValueError as e:
66 print(f"Error: {e}")
67
68
69def delete_task_flow(manager):
70 """Flujo para eliminar una tarea."""
71 print("\n--- Eliminar Tarea ---")
72 list_tasks_flow(manager)
73
74 try:
75 task_id = int(input("\nIngresa el ID de la tarea a eliminar: "))
76 confirm = input(f"Seguro que quieres eliminar la tarea #{task_id}? (s/n): ")
77 if confirm.lower() == "s":
78 task = manager.delete_task(task_id)
79 print(f"\nTarea eliminada: {task.title}")
80 else:
81 print("Operacion cancelada.")
82 except ValueError as e:
83 print(f"Error: {e}")
84
85
86def search_tasks_flow(manager):
87 """Flujo para buscar tareas."""
88 print("\n--- Buscar Tareas ---")
89 keyword = input("Palabra a buscar: ").strip()
90
91 try:
92 results = manager.search_tasks(keyword)
93 if not results:
94 print(f"No se encontraron tareas con '{keyword}'.")
95 return
96
97 print(f"\nResultados para '{keyword}': {len(results)} tarea(s)")
98 for task in results:
99 print()
100 print(task)
101 except ValueError as e:
102 print(f"Error: {e}")
103
104
105def stats_flow(manager):
106 """Flujo para mostrar estadisticas."""
107 print("\n--- Estadisticas ---")
108 stats = manager.get_stats()
109
110 print(f" Total de tareas: {stats['total']}")
111 print(f" Completadas: {stats['completed']}")
112 print(f" Pendientes: {stats['pending']}")
113
114 if stats["total"] > 0:
115 percentage = (stats["completed"] / stats["total"]) * 100
116 bar_length = 20
117 filled = int(bar_length * stats["completed"] / stats["total"])
118 bar = "█" * filled + "░" * (bar_length - filled)
119 print(f" Progreso: [{bar}] {percentage:.0f}%")
120
121
122def main():
123 """Funcion principal del programa."""
124 print("\nBienvenido al Gestor de Tareas")
125 manager = TaskManager()
126
127 while True:
128 show_menu()
129 option = input("Elige una opcion: ").strip()
130
131 if option == "1":
132 add_task_flow(manager)
133 elif option == "2":
134 list_tasks_flow(manager, show_all=True)
135 elif option == "3":
136 list_tasks_flow(manager, show_all=False)
137 elif option == "4":
138 complete_task_flow(manager)
139 elif option == "5":
140 delete_task_flow(manager)
141 elif option == "6":
142 search_tasks_flow(manager)
143 elif option == "7":
144 stats_flow(manager)
145 elif option == "0":
146 print("\nHasta luego! Tus tareas estan guardadas.")
147 break
148 else:
149 print("Opcion no valida. Elige un numero del 0 al 7.")
150
151
152if __name__ == "__main__":
153 main()
Para ejecutar el programa, abre una terminal en la carpeta del proyecto y escribe:
1# Ejecutar el gestor de tareas
2python main.py
Ideas para mejorar el proyecto
Ya tienes un gestor de tareas funcional. Aqui tienes algunas ideas para seguir practicando y mejorar el proyecto:
Nivel facil
- Colores en la terminal: Instala la libreria
colorama(pip install colorama) y agrega colores al menu y los mensajes. Por ejemplo, tareas completadas en verde y pendientes en amarillo. - Ordenar tareas: Agrega una opcion para ordenar las tareas por fecha de creacion, por titulo (alfabeticamente) o por estado.
- Editar tareas: Agrega la posibilidad de cambiar el titulo o la descripcion de una tarea existente.
Nivel intermedio
- Prioridades: Agrega un campo de prioridad (alta, media, baja) a las tareas y permite filtrar por prioridad.
- Fechas limite: Agrega una fecha limite a las tareas y muestra alertas cuando una tarea esta por vencer.
- Categorias: Permite asignar categorias a las tareas (trabajo, personal, estudio) y filtrar por categoria.
Nivel avanzado
- Base de datos SQLite: En lugar de JSON, usa SQLite para almacenar las tareas. Python incluye el modulo
sqlite3sin necesidad de instalar nada. - Interfaz grafica: Crea una version con interfaz grafica usando
tkinter(viene incluido con Python). - API REST: Convierte el gestor en una API web usando Flask o FastAPI — asi podras acceder a tus tareas desde un navegador.
Conclusion del Curso de Python
¡Felicidades! Has completado el Curso de Python desde Cero. A lo largo de 10 articulos, has pasado de no saber nada de programacion a construir un proyecto completo con multiples archivos, clases, persistencia de datos y manejo de errores.
Repasemos todo lo que aprendiste:
| Articulo | Tema |
|---|---|
| Parte 1 | Instalacion de Python y tu primer programa |
| Parte 2 | Variables y tipos de datos |
| Parte 3 | Condicionales (if, elif, else) |
| Parte 4 | Bucles (for, while) y listas |
| Parte 5 | Funciones y diccionarios |
| Parte 6 | Strings y metodos de texto |
| Parte 7 | Programacion orientada a objetos (POO) |
| Parte 8 | Archivos y modulos |
| Parte 9 | Manejo de errores y excepciones |
| Parte 10 | Proyecto final: gestor de tareas |
¿Que sigue despues de este curso?
Ahora que dominas los fundamentos de Python, tienes muchas opciones para seguir creciendo:
- Desarrollo Web: Aprende Flask o Django para crear aplicaciones web con Python. Flask es mas simple para empezar, Django es mas completo para proyectos grandes.
- Ciencia de Datos: Aprende pandas, NumPy y Matplotlib para analizar y visualizar datos. Es una de las areas mejor pagadas en tecnologia.
- Automatizacion: Usa Python para automatizar tareas repetitivas: renombrar archivos, extraer datos de paginas web (web scraping con BeautifulSoup), enviar emails automaticos, etc.
- APIs REST: Aprende FastAPI para crear APIs modernas y rapidas. Es el framework Python mas popular para APIs.
- Machine Learning: Aprende scikit-learn y TensorFlow para crear modelos de inteligencia artificial.
- Bases de datos: Aprende SQL y como conectar Python con bases de datos como PostgreSQL o MySQL.
Comments
Sign in to leave a comment
No comments yet. Be the first!