Este tutorial adapta pedagógicamente el Día 24. Las secciones 📝 Ejercicio original del curso provienen de los archivos del curso. Los retos 🟢🟡🟠🔴, el proyecto extra y el proyecto integrador son creaciones de esta adaptación. Las correcciones al material original aparecen como 🛠️ Nota técnica.
Nota sobre las verificaciones: todos los ejemplos con archivos se ejecutaron con Python 3.14 en Windows: los modos
"r","w"y"a",readlines,strip, los errores deint("")y de archivos inexistentes, las rutas de Windows dentro de un string y la lectura de tildes con y sinencoding. Los resultados que aparecen aquí son los obtenidos. La parte del juego de la serpiente se revisó siguiendo la lógica del código.
Tabla de contenidos
- Antes de empezar
- El problema: el récord que se olvida
- Abrir, leer, escribir y cerrar archivos
- Reto: guardar el récord de la serpiente en un archivo
- Rutas absolutas y relativas
- 🚀 Proyecto del día: la Combinación de Correspondencia (Mail Merge)
- 🌟 Proyecto extra: la Bitácora del Huerto Escolar
- 🏆 Proyecto integrador del Día 24: Generador de Informes para Acudientes
- 🧩 Comprueba lo aprendido
- 🤖 Programar con apoyo de IA
- 🛠️ Correcciones técnicas al material original
- 📋 Matriz de trazabilidad
- 📦 Evidencias de aprendizaje del Día 24
0. Antes de empezar
(Fuentes: 181 - Day 24 Goals- what you will make by the end of the day.md, 188 - What's the correct solution- What's the best answer- What's the right way-.md)
Hasta hoy, todo lo que hacían nuestros programas desaparecía al cerrarlos. Hoy aprenderemos a guardar y leer información en archivos, y a movernos entre carpetas con rutas.
Haremos dos cosas:
- Agregar un récord (puntaje más alto) al juego de la serpiente, que se conserve entre partidas.
- Automatizar una tarea repetitiva: escribir muchas cartas iguales cambiando solo el nombre, como invitaciones a un cumpleaños o a una graduación.
Mensaje de cierre del curso: ¿cuál es la solución correcta? No hay una solución correcta: hay tu solución y el razonamiento que te llevó a ella. El curso cita a Donald Knuth, autor de The Art of Computer Programming, sobre los peligros de la optimización prematura: no intentes que tu código sea lo más rápido o lo más corto posible. Busca que sea legible. Si otra persona entiende tu código sin esfuerzo, lo lograste. Como le dijo un profesor a Angela sobre sus ensayos: "Escribe para que otros entiendan lo que quieres decir", no para sonar inteligente.
Prerequisito general: el juego de la serpiente de los Días 20 y 21, conversión de tipos con
int()ystr()(Día 2), f-strings (Día 2), buclesfor(Día 5), listas (Día 4) y métodos de strings.
1. El problema: el récord que se olvida
(Fuente: 182 - Add a High Score to the Snake Game.md)
🎯 Objetivo de aprendizaje
- Agregar un récord al juego de la serpiente y reiniciar la partida sin cerrar el programa.
- Explicar por qué las variables no sobreviven al cierre del programa.
📝 Ejercicio original del curso: récord y reinicio
Cambios en Scoreboard:
- Nuevo atributo
self.high_score = 0. - El método
game_over()se reemplaza porreset():
def reset(self):
if self.score > self.high_score:
self.high_score = self.score
self.score = 0
self.update_scoreboard()¡El orden importa! Si pusieras self.score = 0 antes del if, el puntaje nunca superaría al récord.
self.clear()pasa a estar dentro deupdate_scoreboard(). Antes no se podía hacer así, porque el GAME OVER necesitaba conservar el puntaje en pantalla. Ahora que no hay GAME OVER, se simplifica y se evita llamarclear()en dos lugares.- El marcador muestra:
f"Score: {self.score} High Score: {self.high_score}".
Cambios en Snake: un método reset() que "reinicia" la serpiente:
def reset(self):
for seg in self.segments:
seg.goto(1000, 1000) # manda los segmentos viejos fuera de la pantalla
self.segments.clear() # vacía la lista
self.create_snake()
self.head = self.segments[0]El curso descubre que self.segments.clear() no borra las tortugas de la pantalla: solo las quita de la lista. Por eso primero las envía a (1000, 1000), fuera de la ventana de 600 × 600.
Cambios en main.py: al chocar con la pared o la cola, ya no se hace game_is_on = False; se llama scoreboard.reset() y snake.reset().
Análisis de esta adaptación: los segmentos enviados a (1000, 1000) siguen existiendo en la memoria. Tras muchas partidas se acumulan tortugas invisibles. Una alternativa más limpia es
seg.hideturtle(). Para un juego escolar la diferencia es pequeña, pero es un buen ejemplo de que "que no se vea" no es lo mismo que "que no exista".
📖 ¿Por qué se pierde el récord?
El curso lo demuestra con un ejemplo mínimo:
a = 3
a = int(input("¿Qué valor quieres para a? ")) # el usuario escribe 12
print(a) # 12Si vuelves a ejecutar el programa, a vuelve a ser 3. Cada ejecución empieza desde cero: las variables viven en la memoria RAM y se borran al terminar. Con el récord pasa lo mismo.
¿Cómo lo harías sin computador? Lo anotarías en una libreta o en un documento de Word y lo leerías la próxima vez que juegues. Eso haremos con Python: escribir y leer un archivo.
2. Abrir, leer, escribir y cerrar archivos
(Fuente: 183 - How to Open, Read, and Write to Files using the -with- Keyword.md)
🎯 Objetivo de aprendizaje
- Usar
open()con los modos"r","w"y"a". - Explicar por qué se usa
with.
📖 Explicación conceptual
open() es una función incorporada (no hay que importarla). Recibe el nombre del archivo y el modo:
| Modo | Significado | Si el archivo no existe | Si el archivo existe |
|---|---|---|---|
"r" (por defecto) |
Leer (read) | FileNotFoundError |
Lo lee |
"w" |
Escribir (write) | Lo crea | Borra todo su contenido y escribe desde cero |
"a" |
Agregar (append) | Lo crea | Escribe al final, sin borrar |
Versión 1 del curso (abrir y cerrar a mano):
file = open("my_file.txt")
contents = file.read() # devuelve TODO el contenido como un string
print(contents)
file.close() # libera los recursos del computador¿Por qué cerrar? Un archivo abierto consume recursos, como una pestaña del navegador. Con 20 o 30 pestañas, el computador se pone lento. Consejo del curso: cierra las pestañas y los archivos que ya no uses.
Versión 2 (la recomendada): with
with open("my_file.txt") as file:
contents = file.read()
print(contents)
# al salir del bloque, Python cierra el archivo automáticamenteEscribir y agregar:
with open("my_file.txt", mode="w") as file:
file.write("Nuevo texto.") # reemplaza todo el contenido
with open("my_file.txt", mode="a") as file:
file.write("\nNuevo texto.") # \n = salto de línea, agregado al final(Verificado: escribir "Hola\n" con "w" y luego "Nuevo texto" con "a" deja el archivo con 'Hola\nNuevo texto'.)
🛠️ Nota técnica (verificada): las tildes y la ñ
El curso no especifica la codificación de los archivos. En español esto es importante. En Windows, si no se indica, Python usa la codificación del sistema (en la prueba, cp1252), mientras que los editores modernos como PyCharm y VS Code guardan en UTF-8. Resultado de la prueba: un archivo UTF-8 con "Querida Sofía, ñandú" leído sin encoding se ve como "Querida SofÃa, ñandú".
Solución: indica siempre la codificación:
with open("carta.txt", encoding="utf-8") as file:
contents = file.read()Adóptalo como buena práctica desde hoy:
encoding="utf-8"en todoopen()con textos en español.
⚠️ Errores frecuentes
| Error | Mensaje o síntoma | Solución |
|---|---|---|
| Escribir en un archivo abierto para leer | io.UnsupportedOperation: not writable |
Usa mode="w" o mode="a" |
Usar "w" cuando querías agregar |
Desaparece todo el contenido anterior | Usa "a" |
Nombre de archivo sin extensión ("my_file") |
FileNotFoundError |
Escribe "my_file.txt" |
file.write(5) |
TypeError: write() argument must be str, not int |
Convierte: file.write(str(5)) |
No indicar encoding |
"SofÃa" en lugar de "Sofía" | encoding="utf-8" |
Retos adicionales (creados para esta adaptación)
- 🟢 Reto 1 — Aplicación: crea un programa que pida tu nombre y lo agregue a
asistencia.txt, uno por línea. Ejecútalo 3 veces. - 🟡 Reto 2 — Ampliación: lee
asistencia.txte imprime cuántas personas hay y la lista numerada. - 🟠 Reto 3 — Desafío: agrega la fecha y la hora a cada registro (investiga
datetime.now()). - 🔴 Reto 4 — Pensamiento computacional: ¿qué pasa si dos personas escriben su nombre con distintas mayúsculas ("ana" y "Ana")? Diseña cómo evitar duplicados antes de escribir.
3. Reto: guardar el récord de la serpiente en un archivo
(Fuente: 184 - Challenge- Read and Write the High Score to a File in Snake.md)
📝 Ejercicio original del curso
Enunciado: crear data.txt con el número 0 y usarlo para que el récord sobreviva al cierre del juego.
🔍 Antes de programar
- ¿En qué momento hay que leer el archivo? ¿Y en qué momento escribir?
read()devuelve un string. ¿Qué necesitas para compararlo con el puntaje?write()solo acepta strings. ¿Cómo guardas un número?
Solución del curso:
# En Scoreboard.__init__ (en lugar de self.high_score = 0):
with open("data.txt") as data:
self.high_score = int(data.read())
# En Scoreboard.reset(), dentro del if del nuevo récord:
with open("data.txt", mode="w") as data:
data.write(f"{self.high_score}")Prueba del curso: logra un récord de 2, detén el programa, vuelve a ejecutarlo… y el récord 2 sigue ahí.
El curso aclara que el mensaje
KeyboardInterruptal pulsar Detener es normal: el juego está hecho para seguir "para siempre".
🛠️ Nota técnica (verificada): esta solución falla en dos situaciones:
- Si
data.txtno existe →FileNotFoundError: [Errno 2] No such file or directory.- Si
data.txtestá vacío →ValueError: invalid literal for int() with base 10: ''.Ambas son comunes, por ejemplo cuando un compañero descarga tu juego sin el archivo. Por ahora puedes manejarlas con
try/except(Día 13). El curso profundiza en el manejo de excepciones en el Día 30.
Retos adicionales (creados para esta adaptación)
- 🟢 Reto 1: borra
data.txty ejecuta el juego. Anota el error exacto. Luego déjalo vacío y repite. - 🟡 Reto 2: maneja ambos errores para que, en esos casos, el récord empiece en 0 y el archivo se cree solo.
- 🟠 Reto 3: guarda también el nombre del dueño del récord (pídelo con
screen.textinputal superarlo). - 🔴 Reto 4: guarda los 5 mejores puntajes, uno por línea, ordenados de mayor a menor.
4. Rutas absolutas y relativas
(Fuente: 185 - Understand Relative and Absolute File Paths.md)
🎯 Objetivo de aprendizaje
- Diferenciar una ruta absoluta de una relativa.
- Usar
./y../para navegar entre carpetas.
📖 Explicación conceptual
Analogía del curso: un dinosaurio busca un huevo dorado en un mapa. Para darle indicaciones dices: "Sigue hasta el volcán, gira a la derecha en la serpiente, a la izquierda en la palmera…". Una ruta son las indicaciones para llegar a un archivo a través de las carpetas.
Estructura de ejemplo del curso:
/ (raíz) ← en Windows suele ser C:\ ; en Mac, Macintosh HD
└── Work/
├── report.doc
└── Project/
└── talk.pptRuta absoluta: empieza siempre desde la raíz.
/Work/report.doc/Work/Project/talk.ppt- En Windows:
C:/Users/TuUsuario/Desktop/my_file.txt
Ruta relativa: empieza desde el directorio de trabajo, la carpeta en la que "estás".
| Estás en… | Quieres llegar a… | Ruta relativa |
|---|---|---|
Project |
talk.ppt |
./talk.ppt (o solo talk.ppt) |
Work |
talk.ppt |
./Project/talk.ppt |
Project |
report.doc |
../report.doc |
./= "en esta carpeta" (se puede omitir).../= "sube a la carpeta madre".../../sube dos niveles.
📝 Ejercicio original del curso
- Mover
my_file.txtal Escritorio y buscar su ubicación (clic derecho → Propiedades en Windows; Obtener información en Mac). - Reto A: leerlo con una ruta absoluta, por ejemplo
"C:/Users/TuUsuario/Desktop/my_file.txt". - Reto B: leerlo con una ruta relativa desde el proyecto. El proyecto está en
.../TuUsuario/PycharmProjects/day-24, así que hay que subir dos niveles hasta la carpeta del usuario y bajar al Escritorio:"../../Desktop/my_file.txt".
Conclusión del curso: ninguna es siempre mejor. Conocer ambas te permite elegir la más adecuada.
🛠️ Notas técnicas (verificadas)
1. Las barras en Windows. El curso dice que en Python se puede escribir / también en Windows, y es cierto. Lo que no se puede es copiar la ruta de Windows tal cual en un string normal:
p = "C:\Users\ana\Desktop\my_file.txt"
# SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes ... truncated \UXXXXXXXX escapeLa \ es un carácter de escape (como en \n) y \U inicia un código Unicode. Soluciones: usar /, un string crudo r"C:\Users\ana\..." o duplicar las barras "C:\\Users\\...".
2. ¿Relativa a qué? El curso explica que la ruta relativa parte de la carpeta de main.py. Eso es lo que ocurre en PyCharm, porque ejecuta el programa desde la carpeta del proyecto. En realidad, la ruta relativa parte del directorio de trabajo actual (os.getcwd()), que depende de desde dónde se ejecuta el programa. En VS Code o en la terminal puede ser otra carpeta, y entonces aparece FileNotFoundError aunque el archivo esté "al lado" de main.py. Una forma robusta de construir rutas relativas al archivo del programa:
from pathlib import Path
CARPETA = Path(__file__).parent
with open(CARPETA / "data.txt", encoding="utf-8") as data:
...Retos adicionales (creados para esta adaptación)
- 🟢 Reto 1: con la estructura
Colegio/Grado10/Notas/matematicas.txt, escribe la ruta relativa desdeGrado10y desdeNotashaciaColegio/reglamento.txt. - 🟡 Reto 2: imprime
os.getcwd()en PyCharm y en la terminal. ¿Coinciden? Explica. - 🟠 Reto 3: reescribe el récord de la serpiente usando
Path(__file__).parenty ejecuta el juego desde otra carpeta con la terminal. - 🔴 Reto 4: investiga
os.listdir()oPath.iterdir()y escribe un programa que liste todos los.txtde una carpeta con su tamaño.
5. 🚀 Proyecto del día: la Combinación de Correspondencia (Mail Merge)
(Fuentes: 186 - Introducing the Mail Merge Challenge.md, 187 - Solution & Walkthrough for the Mail Merge Project.md)
Problema
Tienes una carta modelo que dice Dear [name], y una lista de invitados. Debes generar una carta por invitado, reemplazando [name] por su nombre.
Contexto
La "combinación de correspondencia" se usa en la vida real para invitaciones, certificados, circulares para acudientes y correos a clientes. Automatizarla ahorra horas de trabajo repetitivo.
Estructura de carpetas del código inicial del curso
mail-merge-project-start/
├── main.py
├── Input/
│ ├── Letters/
│ │ └── starting_letter.txt ← la carta modelo con [name]
│ └── Names/
│ └── invited_names.txt ← un nombre por línea
└── Output/
└── ReadyToSend/ ← aquí van las cartas (incluye un archivo de ejemplo)Los nombres de carpetas y archivos salen de las lecciones
186y187. Si tu código inicial tiene nombres ligeramente distintos, ajusta las rutas.
Regla del curso: "sin trampas". No se vale mover archivos a mano: todo se hace con rutas.
Resultado esperado: un archivo letter_for_{nombre}.txt por invitado dentro de ReadyToSend.
Restricciones técnicas
with open(...), rutas relativas y tres métodos que el curso pide investigar en la documentación:
| Método | Qué hace | Ejemplo verificado |
|---|---|---|
readlines() |
Devuelve una lista con cada línea del archivo | ['Aang\n', 'Zuko\n', 'Appa\n'] |
str.replace(viejo, nuevo) |
Devuelve un nuevo string con el reemplazo | "Me gustan los plátanos".replace("plátanos", "mangos") |
str.strip() |
Quita espacios y saltos de línea al inicio y al final | " Hola mundo \n".strip() → "Hola mundo" |
Filosofía del curso: es imposible enseñar todos los métodos. Un desarrollador profesional busca la información cuando la necesita, la entiende y la aplica.
🛠️ Nota: en la transcripción aparece "deadline()"; se refiere a
readline()(en singular), que lee una línea. Aquí se necesitareadlines(), con s, que devuelve todas las líneas.
Planificación
🔍 Antes de programar
- Entradas: ¿qué dos archivos se leen? Escribe sus rutas relativas desde
main.py. - Proceso: ¿qué se repite para cada nombre?
- Salidas: ¿cómo se llama cada archivo generado y en qué carpeta va?
- ¿Qué crees que pasará con el
\nal final de cada nombre?
Construcción paso a paso (siguiendo la solución del curso)
Versión 1 — Leer los nombres: with open("./Input/Names/invited_names.txt"), primero con read() (un solo string) y luego con readlines() (una lista).
Versión 2 — Leer la carta: constante PLACEHOLDER = "[name]" y letter_contents = letter_file.read(), desde ./Input/Letters/starting_letter.txt.
Versión 3 — Reemplazar: un bucle que crea new_letter = letter_contents.replace(PLACEHOLDER, name) e imprime el resultado.
Versión 4 — El error del salto de línea. Al imprimir, todas las cartas menos la última tienen un salto de línea después del nombre: "Dear Aang" + salto + ",". Es el \n que trae readlines(). La solución es stripped_name = name.strip().
Versión final — Escribir cada carta: with open(f"./Output/ReadyToSend/letter_for_{stripped_name}.txt", mode="w") as completed_letter: y completed_letter.write(new_letter). Como el archivo no existe, el modo "w" lo crea.
🛠️ Nota técnica: en el video de la solución, la carta modelo y las de salida aparecen con extensión
.docx, mientras que la introducción habla de archivos.txt. Escribir texto plano en un archivo llamado.docxno crea un documento de Word válido: un.docxreal es un paquete comprimido con XML adentro, y Word podría decir que el archivo está dañado. Usa.txt. Para generar documentos de Word de verdad existe la libreríapython-docx, que no es parte de este día.
Mejora de esta adaptación: agrega
encoding="utf-8"a los tresopen(). Con nombres como "Sofía" o "Muñoz", sin esto las cartas pueden salir con caracteres extraños (sección 2).
Pruebas
| Caso | Resultado esperado |
|---|---|
| Ejecutar el programa | Un archivo por nombre en ReadyToSend |
Abrir letter_for_Aang.txt |
Dice "Dear Aang," en la misma línea, sin salto |
| El último nombre de la lista | Su carta es igual a las demás |
| Agregar "Sofía Muñoz" a la lista | Su carta muestra bien la tilde y la ñ |
Una línea vacía al final de invited_names.txt |
⚠️ ¿Qué archivo se crea? ¿Cómo lo evitas? |
| Ejecutar desde otra carpeta en la terminal | ⚠️ ¿Encuentra los archivos? (nota 2 de la sección 4) |
🧪 Prueba y depuración
Este código tiene cuatro errores. Encuéntralos:
PLACEHOLDER = "[nombre]"
with open("./Input/Names/invited_names.txt") as names_file:
names = names_file.read()
with open("./Input/Letters/starting_letter.txt") as letter_file:
letter_contents = letter_file.read()
for name in names:
new_letter = letter_contents.replace(PLACEHOLDER, name)
with open(f"./Output/ReadyToSend/letter_for_{name}.txt") as completed_letter:
completed_letter.write(new_letter)(Pistas: un marcador que no coincide con la carta; recorrer un string en vez de una lista (¿qué es name en cada vuelta?); falta un strip; y un modo de apertura.)
⭐ Extensión del proyecto
- Varios marcadores:
[name],[date],[place]. - Una lista de invitados con dos columnas:
nombre,apodo. - Un resumen al final: "Se generaron 7 cartas".
6. 🌟 Proyecto extra: la Bitácora del Huerto Escolar
Situación
El proyecto ambiental del colegio tiene un huerto. Cada día, un estudiante registra la temperatura, si se regó y una observación. Hoy lo anotan en un cuaderno que se pierde.
Requisitos
- Un menú en la consola:
1. Registrar día,2. Ver resumen,3. Salir. - Registrar agrega una línea a
bitacora/AAAA-MM.txt(un archivo por mes, dentro de la carpetabitacora) con el formatofecha;temperatura;regado;observación. - Si la carpeta no existe, el programa la crea (investiga
os.makedirsconexist_ok=TrueoPath.mkdir). - Ver resumen lee el archivo del mes y muestra: días registrados, temperatura promedio, días sin riego y la última observación.
- Valida los datos: la temperatura debe ser un número entre −5 y 45, y el riego "si" o "no".
- Usa
encoding="utf-8"y rutas construidas conPath(__file__).parent.
Decisiones que debes tomar
- ¿Qué modo de apertura usas para registrar? ¿Y para leer?
- ¿Por qué separar los campos con
;y no con,? (Piensa en las observaciones.)
Reflexión
¿Qué ventajas tiene un archivo por mes frente a un único archivo gigante?
7. 🏆 Proyecto integrador del Día 24: Generador de Informes para Acudientes
Proyecto integrador creado para esta adaptación. Integra archivos, modos de apertura, rutas, métodos de strings, diccionarios (Día 9), funciones (Días 8 y 10), validación y manejo de errores (Día 13).
Situación problema
Al final de cada periodo, el director de grupo escribe a mano una nota para el acudiente de cada estudiante. Quiere automatizarlo con una plantilla y los datos de cada estudiante.
Pregunta orientadora
¿Cómo diseñar un programa que transforme datos en documentos personalizados, de forma confiable, sin mover archivos a mano?
Requerimientos
- Entradas en
entrada/:plantilla.txt, con los marcadores[acudiente],[estudiante],[promedio],[desempeno]y[mensaje].estudiantes.txt, con una línea por estudiante:estudiante;acudiente;nota1;nota2;nota3.
- Para cada estudiante:
- Calcular el promedio (con un decimal).
- Determinar el desempeño según la escala de tu institución (por ejemplo: Bajo, Básico, Alto, Superior).
- Elegir un mensaje según el desempeño, guardado en un diccionario.
- Generar
salida/informes/informe_{estudiante}.txt, sin espacios en el nombre del archivo (reemplázalos por_).
- Si una línea tiene un error (faltan datos o una nota no es un número), no se detiene: la escribe en
salida/errores.txtcon el número de línea y continúa. - Al final, genera
salida/resumen.txtcon el total de informes, el promedio del grupo y la cantidad de estudiantes por desempeño. - Rutas con
Path(__file__).parent,encoding="utf-8"en todos los archivos y funciones con docstring.
Etapas de desarrollo
- Leer y mostrar los datos en la consola.
- Un informe correcto para un estudiante.
- Todos los informes.
- Manejo de líneas con errores.
- Resumen del grupo.
Entregables
- El código y las carpetas
entrada/ysalida/con un ejemplo de al menos 8 estudiantes ficticios (dos de ellos con errores a propósito). - Una explicación de la estructura de carpetas y las rutas usadas.
Casos de prueba
| Caso | Esperado |
|---|---|
| Estudiante "María José Peña" | Archivo informe_María_José_Peña.txt con tildes correctas |
Línea con la nota "cuatro" |
Registrada en errores.txt; el programa continúa |
| Línea con solo 2 campos | Registrada en errores.txt |
| Ejecutar dos veces | Los informes se reemplazan, no se duplican |
| Ejecutar desde otra carpeta | Funciona igual |
Criterios técnicos
- Ningún
open()sinwith. - Ninguna ruta absoluta en el código.
- Cambiar la plantilla no exige tocar el código.
⚠️ Protección de datos: usa nombres ficticios. Los datos reales de estudiantes y acudientes son información personal protegida.
8. 🧩 Comprueba lo aprendido
Conceptuales
- ¿Qué diferencia hay entre los modos
"w"y"a"? - ¿Por qué se prefiere
with open(...)aopen()conclose()? - ¿De qué depende una ruta relativa?
Análisis de código
with open("notas.txt", mode="w") as f:
f.write("5")
with open("notas.txt", mode="w") as f:
f.write("4")
with open("notas.txt") as f:
print(f.read())¿Qué imprime? ¿Y si el segundo modo fuera "a"?
Predicción
Estás en Colegio/Grado10/Proyecto/. ¿A qué archivo apunta "../../Rectoria/circular.txt"?
Depuración
with open("data.txt") as data:
high_score = data.read()
if 7 > high_score:
print("¡Nuevo récord!")¿Qué error aparece y por qué?
Modificación
Cambia el Mail Merge para que los archivos de salida se llamen invitacion_{nombre}_{fecha}.txt, con la fecha de hoy.
Creación
Escribe un programa que cuente cuántas veces aparece cada palabra en un archivo texto.txt y guarde el resultado en conteo.txt, una palabra por línea.
9. 🤖 Programar con apoyo de IA
Actividad: comprobar afirmaciones sobre archivos.
- Pregunta a una IA: "¿Una ruta relativa en Python es relativa a la ubicación del archivo
.py?". Anota su respuesta. - Compruébalo tú: imprime
os.getcwd()y ejecuta el mismo programa desde dos carpetas distintas en la terminal. ¿La IA tenía razón? - Pídele el código del Mail Merge. ¿Incluye
encoding="utf-8"? Pruébalo con un nombre con tilde en Windows. - Consulta la documentación oficial de
open()(se abre en otra pestaña) y verifica qué dice sobre la codificación por defecto. - Escribe en tu cuaderno qué afirmación de la IA verificaste y con qué fuente.
10. 🛠️ Correcciones técnicas al material original
| Archivo | Afirmación o comportamiento del curso | Observación | Tratamiento |
|---|---|---|---|
183 |
open() sin indicar la codificación |
En Windows, un archivo UTF-8 con "Sofía" se lee como "SofÃa" (verificado con cp1252) |
Nota técnica del Tema 2 |
184 |
int(data.read()) |
Falla si el archivo no existe (FileNotFoundError) o está vacío (ValueError) (verificado) |
Nota técnica del Tema 3 |
185 |
La ruta relativa parte de la carpeta de main.py |
Parte del directorio de trabajo actual; en PyCharm coinciden, en otros entornos no | Nota técnica 2 del Tema 4 |
185 |
En Python se puede escribir / en Windows |
Correcto; pero copiar C:\Users\... en un string normal da SyntaxError (verificado) |
Nota técnica 1 del Tema 4 |
187 |
Carta modelo y cartas de salida .docx |
Texto plano con extensión .docx no es un documento de Word válido; usar .txt |
Nota técnica del proyecto |
187 |
"deadline()" | Error de transcripción: readline(); el proyecto usa readlines() |
Nota del proyecto |
182 |
Los segmentos viejos se envían a (1000, 1000) | Funciona, pero siguen en memoria; hideturtle() es una alternativa |
Análisis del Tema 1 |
11. 📋 Matriz de trazabilidad
| Contenido original | Archivo de origen | Concepto desarrollado | Ejercicio original | Reto adicional | Proyecto relacionado |
|---|---|---|---|---|---|
| Objetivos: récord y Mail Merge | 181 |
Sección 0 | — | — | Secciones 1 y 5 |
Récord, reset de marcador y serpiente, estado que se pierde |
182 |
Tema 1 | Récord en memoria | — | Tema 3 |
open, read, write, close, with, modos |
183 |
Tema 2 | my_file.txt y new_file.txt |
Retos 1–4 del Tema 2 | Secciones 5, 6 y 7 |
Récord en data.txt |
184 |
Tema 3 | Leer y escribir el récord | Retos 1–4 del Tema 3 | — |
Rutas absolutas y relativas, ./, ../ |
185 |
Tema 4 | Archivo en el Escritorio | Retos 1–4 del Tema 4 | Secciones 5, 6 y 7 |
| Mail Merge: planteamiento | 186 |
Sección 5 | Enunciado y estructura | Análisis previo | Sección 7 |
Mail Merge: readlines, replace, strip |
187 |
Sección 5 | Solución completa | Depuración y extensiones | Sección 7 |
| No hay una solución correcta; legibilidad | 188 |
Sección 0 | — | — | Criterios de los proyectos |
| (No existe en el curso original) | — | — | — | Bitácora del Huerto Escolar | Sección 6 |
| (No existe en el curso original) | — | — | — | Informes para Acudientes | Sección 7 |
12. 📦 Evidencias de aprendizaje del Día 24
- Juego de la serpiente con récord persistente y captura del récord después de reiniciar el programa.
- Mail Merge funcionando, con captura de la carpeta
ReadyToSendy de una carta. - Un esquema de carpetas con 3 rutas absolutas y 3 relativas escritas por ti.
- Prueba de la codificación: captura de "Sofía" leída sin y con
encoding="utf-8". - Proyecto extra (Bitácora del Huerto) o integrador (Informes para Acudientes).
- Cuaderno de errores:
FileNotFoundError,UnsupportedOperation: not writable,ValueErrorconint(""),TypeErroral escribir un número,SyntaxErrorpor\Uen rutas de Windows, el\ndereadlines()y las tildes dañadas.