Aprende a separar tu código como un profesional — una carpeta a la vez, con preguntas y respuestas de verdad
main.py?
Esta tabla es tu mapa durante toda la actividad. Úsala como referencia en cada paso:
| En el restaurante… | En nuestro programa… | Carpeta |
|---|---|---|
| 🧑🍳 El mesero te atiende y muestra el menú | Lo que el usuario ve y elige en pantalla | menus/ |
| 👨🍳 La cocina prepara el plato (sabe las recetas) | La lógica: qué hacer con los datos | services/ |
| 🔪 Los utensilios que la cocina usa | Herramientas reutilizables para todos | utils/ |
| 🧊 La despensa / nevera donde se guarda la comida | Donde viven los datos del programa | data/ |
data/, utils/, services/ y menus/. Más el archivo main.py en la raíz. Piensen en esto como montar las estaciones del restaurante antes de cocinar: primero organizan el espacio, después viene la comida.
main.py crean un documento de texto vacío y lo renombran a main.py. Ojo: verifiquen que no quede main.py.txt — Windows a veces esconde la extensión.
Esta es la estructura completa que deben tener al final de este paso:
Data/ en vez de data/) puede romper los import en Ubuntu.data/)json que ya viene instalada.
[]. Eso es una lista vacía en JSON. El archivo ya existe y está listo para recibir datos, pero por ahora no tiene nada adentro. La despensa está abierta, simplemente vacía.
Creen este archivo dentro de la carpeta data/:
[]data/ no tiene código Python. Solo archivos de datos. Ninguna capa del programa "vive" aquí — solo se guarda información.utils/)utils/ y que todo el mundo lo use desde allá.
leer_json) y una para guardar (guardar_json). Como el cuchillo y la sartén en una cocina — son las herramientas base que todos usan.
leer_json con un archivo que todavía no existe?
FileNotFoundError. Por eso le ponemos un chequeo: si el archivo no existe, devolvemos [] en lugar de caerse. El programa puede seguir trabajando normalmente aunque sea la primera vez que corre. A eso se llama manejar errores con cuidado.
Creen el archivo utils/file_manager.py:
import json import os def leer_json(ruta): # Si el archivo no existe todavía, devolvemos lista vacía if not os.path.exists(ruta): return [] with open(ruta, "r", encoding="utf-8") as archivo: try: return json.load(archivo) except json.JSONDecodeError: return [] def guardar_json(ruta, datos): with open(ruta, "w", encoding="utf-8") as archivo: json.dump(datos, archivo, indent=4, ensure_ascii=False)
ensure_ascii=False? Para que los acentos y la ñ se guarden correctamente en el archivo. Sin eso, "Café" quedaría guardado como \u00e9.utils/file_manager.py todavía no se puede probar solo — es una herramienta, y alguien tiene que usarla. Ese alguien es la siguiente capa.services/)menus/ o en services/?
services/, la cocina. El menú solo pide la acción; el servicio la prepara. El menú no debería saber cómo se guarda un producto en el JSON — solo debería decirle al servicio "guardá esto" y el servicio sabe qué hacer.
utils/. ¡Reutilizamos lo que ya construimos!
producto_service.py va a importar de utils/file_manager.py?
services/ depende de utils/. Y eso está bien — la cocina depende de los utensilios. Lo que NO debe pasar es que los utensilios dependan de la cocina o del menú. El flujo siempre va en una sola dirección.
Creen services/producto_service.py:
from utils.file_manager import leer_json, guardar_json RUTA_PRODUCTOS = "data/productos.json" def listar_productos(): productos = leer_json(RUTA_PRODUCTOS) print("\n===== PRODUCTOS DISPONIBLES =====") if len(productos) == 0: print("No hay productos publicados todavía.") return for producto in productos: print("--------------------------------") print(f"ID: {producto['id']}") print(f"Nombre: {producto['nombre']}") print(f"Precio: ${producto['precio']}") def crear_producto(): productos = leer_json(RUTA_PRODUCTOS) print("\n===== PUBLICAR PRODUCTO =====") nombre = input("Nombre del producto: ") try: precio = float(input("Precio: ")) except ValueError: print("El precio debe ser un número. Intente de nuevo.") return nuevo_producto = { "id": len(productos) + 1, "nombre": nombre, "precio": precio } productos.append(nuevo_producto) guardar_json(RUTA_PRODUCTOS, productos) print("✅ Producto publicado correctamente.")
try / except ValueError? Porque si el usuario escribe "cinco" en vez de 5000, la conversión float() falla. El try atrapa ese error y muestra un mensaje amable en vez de que el programa explote.menus/)services/. El mesero no cocina — solo anota el pedido y se lo pasa a la cocina.
while True. Muestra el menú una y otra vez, hasta que el usuario elige "Salir" y el programa hace break para salir del bucle. Sin el break, el programa nunca pararía.
Creen menus/menu_principal.py:
from services.producto_service import listar_productos, crear_producto def mostrar_menu_principal(): while True: print("\n====================================") print(" MI MINI MARKET") print("====================================") print("1. Ver productos") print("2. Publicar producto") print("3. Salir") opcion = input("Seleccione una opción: ") if opcion == "1": listar_productos() elif opcion == "2": crear_producto() elif opcion == "3": print("¡Gracias por usar Mi Mini Market!") break else: print("Opción no válida. Intente de nuevo.")
import de la primera línea. El menú solo sabe que existen esas dos funciones — no sabe cómo funcionan por dentro. Eso es encapsulación.main.py: encender el programamain.py es el botón de encendido. Su único trabajo es llamar al menú principal. Por eso es cortísimo — con 3 líneas basta. Toda la magia ya está repartida en las capas.
if __name__ == "__main__" tan raro?
main.py por algún motivo, el menú no se activa solo. No es obligatorio entenderlo a fondo hoy, pero es buena práctica acostumbrarse a verlo.
Abren el archivo main.py que ya crearon y escriben esto:
from menus.menu_principal import mostrar_menu_principal if __name__ == "__main__": mostrar_menu_principal()
mi_mini_market/:python main.py
Este es el flujo exacto de dependencias en tu proyecto:
file_manager.py?
Así queda la estructura final completa con sus archivos:
File "..." dice dónde. Nunca borren todo — solo busquen el punto exacto que falla.
| Error en pantalla | Causa más probable | Solución |
|---|---|---|
| ModuleNotFoundError: No module named 'menus' |
Estás corriendo Python desde la carpeta equivocada | Asegúrate de ejecutar python main.py dentro de mi_mini_market/ |
| FileNotFoundError: data/productos.json |
La carpeta o el archivo no existe o está mal escrito | Verifica que se llame exactamente data/productos.json (todo en minúscula) |
| El programa se cierra de inmediato | Falta el while True o la sangría está mal |
Revisa la indentación en menu_principal.py — Python es muy estricto con los espacios |
| KeyError: 'nombre' | Un producto en el JSON no tiene esa "llave" | Borra el contenido de productos.json y déjalo en [] |
| Acentos y ñ se ven raros | Falta encoding="utf-8" |
Ya viene en file_manager.py; verifica que no lo hayas borrado |
guardar_json escribió el producto en data/productos.json. Las variables se borran al cerrar, pero los archivos permanecen. Eso es la persistencia, y la lograron ustedes con sus propias capas. 🏆
usuarios.json y usuario_service.py?
Antes de entregar, respondan estas preguntas en grupo. Anótenlas para la exposición:
Separaron responsabilidades, reutilizaron herramientas, manejaron errores y lograron persistencia.
Eso es pensar como programadores profesionales.