Saltar al contenido
🐍 Curso de Python
/

Módulo 1 · Lección 45 de 59

Escribir ficheros de texto

Los cuatro modos de apertura, la diferencia entre borrar y añadir, y cómo dejar los datos guardados en disco sin perder nada.

⏱ 11 min de lectura

Un programa que solo imprime en pantalla olvida todo al terminar. Guardar en un fichero es lo que convierte un ejercicio en una herramienta: un informe que puedes enviar, una lista que sobrevive al reinicio, un registro de lo que ha ido pasando.

Escribir se hace con el mismo open() de la lección anterior, pero con un segundo argumento que es donde está toda la miga: el modo. Elegir mal el modo es la forma más rápida de borrar un fichero sin querer.

Los cuatro modos#

python
with open("notas.txt", "w", encoding="utf-8") as fichero:
        fichero.write("Hola\n")

Ese "w" es el modo. Hay cuatro que necesitas conocer:

ModoNombreSi el fichero existeSi no existe
"r"Lectura (por defecto)Lo leeFileNotFoundError
"w"EscrituraBorra todo el contenidoLo crea
"a"AñadirEscribe al finalLo crea
"x"Creación exclusivaFileExistsErrorLo crea

Cuando no pones modo, Python usa "r". Por eso en la lección anterior bastaba con open("compra.txt", encoding="utf-8").

write() no añade el salto de línea#

Esta es la sorpresa del primer día. print pone un salto al final de cada llamada; write no pone nada:

python
with open("notas.txt", "w", encoding="utf-8") as fichero:
        fichero.write("Primera línea")
    fichero.write("Segunda línea")

El fichero queda así:

notas.txt
Primera líneaSegunda línea

Los saltos de línea los pones tú, con \n:

python
with open("notas.txt", "w", encoding="utf-8") as fichero:
        fichero.write("Primera línea\n")
    fichero.write("Segunda línea\n")
notas.txt
Primera línea
Segunda línea

write() además devuelve el número de caracteres escritos, un dato que casi nunca usarás pero que explica por qué en la consola interactiva te aparece un número suelto después de escribir:

consola
>>> fichero = open("prueba.txt", "w", encoding="utf-8")
>>> fichero.write("Hola\n")
5
>>> fichero.close()

Escribir varias líneas#

Lo más habitual es tener una lista y volcarla. La forma clara es un for con una f-string que añade el salto:

participantes.py
participantes = ["Lucía", "Mateo", "Noa", "Hugo"]

with open("participantes.txt", "w", encoding="utf-8") as fichero:
        for nombre in participantes:
                fichero.write(f"{nombre}\n")
participantes.txt
Lucía
Mateo
Noa
Hugo

Existe también writelines(), que recibe una lista y la escribe entera. Su nombre engaña, porque tampoco añade saltos de línea:

python
participantes = ["Lucía", "Mateo", "Noa", "Hugo"]

with open("participantes.txt", "w", encoding="utf-8") as fichero:
        fichero.writelines(participantes)
participantes.txt
LucíaMateoNoaHugo

Para que sirva de algo hay que darle las líneas ya con su \n, cosa que se hace cómodamente con una comprensión:

python
participantes = ["Lucía", "Mateo", "Noa", "Hugo"]
lineas = [f"{nombre}\n" for nombre in participantes]

with open("participantes.txt", "w", encoding="utf-8") as fichero:
        fichero.writelines(lineas)
participantes.txt
Lucía
Mateo
Noa
Hugo

Otra opción igual de válida es unir la lista con "\n".join(participantes) y hacer un solo write. Elige la que te resulte más legible; el for con f-string es la que menos dudas genera.

Añadir sin borrar: el modo "a"#

diario.py
with open("diario.txt", "w", encoding="utf-8") as fichero:
        fichero.write("Lunes: revisión del presupuesto\n")

with open("diario.txt", "a", encoding="utf-8") as fichero:
        fichero.write("Martes: reunión con el cliente\n")
    fichero.write("Miércoles: entrega de la primera versión\n")
diario.txt
Lunes: revisión del presupuesto
Martes: reunión con el cliente
Miércoles: entrega de la primera versión

Con "a" el cursor se coloca al final del fichero nada más abrirlo, así que todo lo que escribas se suma a lo que ya había. Si el fichero no existía, lo crea. Es el modo de los registros y de cualquier cosa que vaya creciendo.

Crear sin pisar: el modo "x"#

"x" crea el fichero solo si no existe. Si existe, falla en vez de tocarlo:

python
with open("diario.txt", "x", encoding="utf-8") as fichero:
        fichero.write("esto no llega a escribirse\n")
Salida en pantalla
Traceback (most recent call last):
  File "/Users/erwin/curso-python/diario.py", line 1, in <module>
    with open("diario.txt", "x", encoding="utf-8") as fichero:
         ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileExistsError: [Errno 17] File exists: 'diario.txt'

Un registro de actividad#

Este es el ejemplo típico del modo "a": una función que anota lo que va pasando, con su fecha y su hora.

registro.py
from datetime import datetime

RUTA_REGISTRO = "actividad.log"


def anotar(mensaje: str) -> None:
        """Añade una línea al registro con la fecha y la hora del momento."""
    momento = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
    with open(RUTA_REGISTRO, "a", encoding="utf-8") as fichero:
                fichero.write(f"[{momento}] {mensaje}\n")


anotar("Programa iniciado")
anotar("Cargados 128 registros de clientes")
anotar("Aviso: 3 registros sin teléfono")
anotar("Programa terminado")

El programa no imprime nada. Lo que deja en actividad.log es esto:

actividad.log
[19/09/2026 13:45:17] Programa iniciado
[19/09/2026 13:45:17] Cargados 128 registros de clientes
[19/09/2026 13:45:17] Aviso: 3 registros sin teléfono
[19/09/2026 13:45:17] Programa terminado

La fecha y la hora serán las de tu ejecución, claro. Y si vuelves a lanzar el programa, las nuevas líneas se añaden debajo en vez de sustituir a las anteriores: ahí está la gracia del modo "a".

Dos detalles del diseño que conviene copiar. La ruta está en una constante en mayúsculas, arriba del todo, para cambiarla en un solo sitio. Y la función abre y cierra el fichero en cada llamada, que es más lento pero garantiza que, si el programa se cuelga, todo lo anotado hasta ese momento ya está en el disco. En un registro, eso es justo lo que quieres.